Nokia nmake Product Builder


Nokia nmake Product Builder
3.0 Release Notes

Table of Contents

Released: 1993

1. Introduction

2. New Features
2.1 Variables
2.2 Common Actions
2.3 Assertion Operators
2.4 Special Atoms
2.5 Edit Operators
2.6 Scan Rules
2.7 Enhancement in cpp
2.8 Enhancement in probe
2.9 Miscellaneous

3. Changes Impacting 2.2 Makefiles
3.1 Changes in Variables
3.2 Changes in Assertion Operators
3.3 Changes in Command Line Options
3.4 Changes in Special Atoms
3.5 Changes in Edit Operators
3.6 Changes in Scan Rules
3.7 Changes in cpp
3.8 Change in probe Output
3.9 Changes in coshell
3.10 Miscellaneous

4. Bug Fixes
4.1 Fixes in Handling Variables
4.2 Fixes in Handling Common Actions
4.3 Fixes in Handling Assertion Operators
4.4 Fixes in Handling Command Line Options
4.5 Fixes in Handling Special Atoms
4.6 Fixes in Scanning
4.7 Fixes in Viewpathing
4.8 Fixes in Handling Metarules
4.9 Fixes in Programming Constructs
4.10 Fixes in cpp
4.11 Fixes in probe
4.12 Fixes in ccc
4.13 Miscellaneous

5. Known Bugs and Remarks
5.1 Known Bugs
5.2 Remarks

6. Conclusion

1. Introduction

nmake 3.0 is a major feature release. It is now available on the following machines:

Machine Type Operating System
Amdahl UTS2.1
DataGeneral SVR4.2
HP9000/7xx HP-UX 9.0
HP9000/8xx HP-UX 8.0
HP9000/8xx HP-UX 9.0
Motorola88100 SVR4.1
NCR/486 SVR4.2
Pyramid-mips DC/OSx1.0
Pyramid OSx5.1a
RISC6000 AIX 3.2
SGI 5.1-alpha
StarServer-FT S300-b20
Sun3 SunOS4.0
Sun4 SunOS4.1
Sun4 SunOS5 (Solaris2.x)
3B2/700 SVR3.2

In this release, nmake dynamically allocates buffer space and generates machine-independent object files and state files (i.e., *.mo and *.ms files). In addition, the performance of cpp has also been greatly improved. This document presents the new features, discusses changes affecting nmake 2.2 makefiles, and explains bug fixes as well as known bugs.

Certain 2.2 makefiles must be upgraded for 3.0. The simplest approach to upgrading 2.2 makefiles is to review the existing local rules and the makefiles of your project. After becoming familiar with the local configuration, read this document and note any changes that may be important. Update the local files as needed for any changes included in this document. It is not necessary to make any changes to the delivered base rules file ( The final step in the upgrade is to do a test build to verify that the changes made in the makefiles are correct.

2. New Features

The following new features are included in this release.

2.1 Variables

  1. Auxiliary Values in Variables and New :VP and :VA Edit Operators
    Each variable in 3.0 may have both a primary value and an auxiliary (hidden) value. The new variable assignment operator &= is used to set the auxiliary value. The edit operator :VP gives the primary value of the token, and :VA gives the auxiliary value of the token. For example:
        X = dummy
        X &= dummy2
    at this point, $(X) expands to dummy dummy2. If X is assigned a new primary value:
        X = xyz
    then $(X) expands to xyz dummy2, $(X:VP) expands to xyz, and $(X:VA) expands to dummy2. If X is assigned a new auxiliary value:
        x &= abc
    then $(X) expands to xyz abc, $(X:VP) expands to xyz, and $(X:VA) expands to abc.
    Both the :VP and the :VA edit operators return variable values without expansion. For example,
        Y = $(X)
        Y &= efg
    The primary and auxiliary values of Y are $(X) and efg respectively. Please note that in this example X's auxiliary value becomes Y's primary value.
    Note: the auxiliary value is not saved in the state file (*.ms file).
  2. Scoped Variables
    If X=x is added to a prerequisite list, X is set to x while the action is being expanded. This will not affect other targets in the same makefile because X is already frozen. For example:
        x.o : .IMPLICIT CCFLAGS=-g
    Here, -g is only applied to generating x.o. This feature allows user to apply certain flags only on those specified files.
  3. New Base Rule Variables ancestor_list and ancestor_source
    Two base rule variables, ancestor_list and ancestor_source have been added to parameterize lib and include directories used with ancestor. nmake searches for libraries and headers in the directory names lib and include from current working directory up to the level specified in ancestor. One may redefine ancestor_list or ancestor_source to have nmake search files in other directory names.
    The default value for ancestor_source is null. The default value for ancestor_list is:
        ancestor_list = $(ancestor_source) .SOURCE.a lib .SOURCE.h include
    ancestor_list contains the .SOURCE.x search_dirname_for_.x pairs. .SOURCE.a lib .SOURCE.h include are the default pairs where nmake searches for libraries and headers when ancestor is not null.
    For example, if one wants nmake to find headers in the directory named hdrs and find libraries in the directory named LIB using the ancestor concept, one may redefine ancestor_list in the makefile to be:
        ancestor_list = .SOURCE.h hdrs .SOURCE.a LIB
    If one also wants nmake to search headers and libraries in the default directories (i.e. include and lib), one should use ancestor_source to define the .SOURCE.x search_dirname_for_.x pairs, since ancestor_list includes the include and lib directory names by default.
  4. New Base Rule Variable: cleanignore
    Files matched by the value of this variable will not be deleted by clean common action.
  5. New Base Rule Variable: force_shared
    If this variable is set to 1, it will cause the re-link of executables with shared libraries when linked shared libraries are out of date. If it is not set, the shared libraries time stamps are ignored.
  6. New Base Rule Variable: prefixinclude
    This variable is used to support C #include "..." compatibility. The default value of this variable is set to 1. If main.c includes a file as #include "prefix/file1.h" (where prefix is at least one level of a directory structure), and if file1.h includes another file as #include "file2.h". By default, nmake first looks in prefix directory for file2.h where the prefix directory is inherited from file1.h. If nmake cannot find file2.h in prefix directory, it searches for it in .SOURCE.h. If prefixinclude is not set, nmake relies exclusively on .SOURCE.h to search for including files; no directory structure is inherited.
  7. New Base Rule Variable: preserve
    When preserve is set to non-null (either 1 or a file match pattern), the install common action will rename the old install target to filename#inodenumber.
  8. New Base Rule Variable: instrument
    This variable supports software packages, such as purify, sentinel, or insight. When instrument is set to one of those packages (e.g., instrument=purify), nmake builds targets with the package. By default, nmake searches /usr/add-on, /usr/addon, and /usr/local directories for the software packages. If the packages are not installed in those directories, a full path name has to be specified (e.g., instrument=/tools/purify).
  9. New Base Rule Variable: arclean
    The generated files (e.g., *.o's) of an archive target can be specified by this variable. The value of this variable can be edit operator expression. The files specified by this variable will be removed after the archive target is made. For example, the Makefile is:
        arclean = N!=a.o|b.o
        lib.a :: a.c b.c c.c d.c
    In this example, all the *.o's except a.o and b.o will be removed.
  10. New Environment Variable COTEMP
    The COTEMP environment variable is generated and set to a different value for each shell command. COTEMP is a 10-character hash name, so names of the form:
    can be up to 14 characters or fewer to satisfy the system V file name length restriction.
    If COSHELL is set to ksh or sh, the value of COTEMP is
    If COSHELL is set to coshell, the value of COTEMP is
    Since internet addresses must be unique between all hosts accessible to coshell, the COTEMP value will be unique for all jobs on all hosts in the local area network.
  11. New Environment Variable MAKECONVERT
    This variable is for compile time makefile conversion. For example, if you have a conversion program nmkgen to convert makefiles from other build tools, such as build, to makefiles, you can do the following:
        export MAKECONVERT=' "nmkgen $(>)"'
    where is a makefile of build. nmake will produce .mo and .ms files from by using nmkgen. remains as a build makefile.
  12. New Environment Variables PACKAGE_id, PACKAGE_id_INCLUDE, PACKAGE_id_LIB
    See "New Assertion Operator :PACKAGE:" in Section 2.3.3.
  13. New Variables in the probe Configuration Files
    The following variables, CC.DYNAMIC, CC.LD, CC.MEMBERS, CC.NM, CC.NMEDIT, CC.NMFLAGS, CC.PIC, CC.SHARED, CC.SO, CC.STATIC and CC.SYMPREFIX have been added to the probe configuration files and can be accessed in makefiles.
    Some of the variables are to support different shared library suffixes, different options to link shared/static libraries, and different options to generate shared libraries among UNIX based operating systems. For example, on HP-UX, the shared library suffix is .sl, the option to link shared library is -ashared, the option to link static library is -aarchive, and the option to generate shared libraries is +z or +Z. Those flags are different on SunOS.
    Since CC.DYNAMIC, CC.STATIC, CC.SHARED and CC.PIC are compiler options, these variables can be used with CCFLAGS. For example, CCFLAGS = -O $(CC.PIC). Thus the makefile can be portable to different machines.
    CC.SYMPREFIX is for the symbol prefix in library symbol table. (See detail discussion of the variables in Appendix B of nmake User's Manual and Reference Guide).
    The following is the probe configuration file of /usr/ucb/cc for nmake on a SUN4, running SunOS4.1.1:
        CC.CC = /usr/ucb/cc
        CC.ALTPP.FLAGS = -Qpath $(CPP:D)
        CC.ALTPP.ENV =
        CC.DYNAMIC = -Bdynamic
        CC.LD = ld
        CC.MEMBERS = `$(NM) $(NMFLAGS) $(*:N=*.a) | \
                      $(SED) $(NMEDIT) -e "s/^/-u /"`
        CC.NM = nm
        CC.NMEDIT = -e '/[      ][TDB][         ]/!d' \
                    -e 's/.*[         ] [TDB][      ][      ]*//'
        CC.NMFLAGS =
        CC.PIC = -pic
        CC.READONLY = -R
        CC.SHARED =
        CC.SO = .so.1
        CC.STATIC = -Bstatic
        CC.STDINCLUDE = /usr/include
        CC.STDLIB = $(LD_LIBRARY_PATH:/:/ /G) /usr/lib /lib /usr/local/lib
        CC.SYMPREFIX = _
        CC.PREROOT =
        CC.UNIVERSE =

2.2 Common Actions

  1. New Common Action: list.symbols
    The list.symbols common action lists the sorted archive symbol names.

2.3 Assertion Operators

  1. New Assertion Operator :FUNCTION:
    The left-hand side (lhs will be used hereafter) is a functional variable, whose value is determined by the action of this assertion at execution time.
        t :FUNCTION: p
    This is the same as
        t : p .SPECIAL .FUNCTION
    However, :FUNCTION: is more readable and should be used. For example,
        view :FUNCTION: 
    	    return $(%:T=F)
    where $(%) is the arguments of the functional variable.
  2. New Assertion Operator :INSTALLPROTO:
    This assertion operator installs $(PROTO) output of right-hand side (rhs will be used hereafter) files into the lhs directory by the install common action. $(PROTO) is a conversion program that converts a prototyped C file to a file that is compatible with ANSI, K&R and C++ dialects of C. rhs files must have #pragma prototyped as the first line and must be valid ANSI C. In the base rules, PROTO is set to proto, which is included in the bin directory of the nmake software package.
  3. New Assertion Operator :PACKAGE: and New Environment Variables
    This assertion operator and the environment variables, PACKAGE_id, PACKAGE_id_INCLUDE, and PACKAGE_id_LIB, facilitate locating include files and libraries of a specified package id. The assertion operator and the environment variables add the directories to be searched for include files and libraries to .SOURCE.h and .SOURCE.a respectively, and eliminate the need for many .SOURCE.h and .SOURCE.a assertions. The package is searched in /usr/add-on, /usr/local, and /home by default when :PACKAGE: is used.
    For example, if one owns and builds a package called ast, which is installed in /usr/add-on, one can specify it in the makefile as:
        :PACKAGE: ast
    nmake will search /usr/add-on/ast/include for include files and /usr/add-on/ast/lib for libraries. One also can use other ast versions (say /home/my/ast), or a different version of include files or libraries by exporting in the environment:
        export PACKAGE_ast=/home/build/ast
        export PACKAGE_ast_INCLUDE=/home/build/ast/include
        export PACKAGE_ast_LIB=/home/build/ast/lib

    Note: the :PACKAGE: changes the variable INCLUDEDIR to be $(INSTALLROOT)/include/id by default. Thus, header files of ast package by default are installed in $(INSTALLROOT)/include/ast. A "-" as the first character of the rhs inhibits the INCLUDEDIR redefinition. If one uses a third-party software package, one should specify it as:
        :PACKAGE: - X11

    :PACKAGE: can be multiply defined, but the most recent :PACKAGE: assertion takes the highest precedence. A "+" in rhs will append the package(s) at the end of the package list, which means it would take the lowest precedence. For example,
        :PACKAGE: ast
        :PACKAGE: xast yast +
    nmake will look for headers and libraries first in the ast package, then in the xast and yast packages.
    When :PACKAGE: is used, nmake automatically links the package library to all the executable targets. For example, if the package is specified as
        :PACKAGE: xx
    all the exectable targets will be linked with a library, -lxx. If there is no libraries in the package named libxx, the following line has to be added in the makefile.
        -lxx : .DONTCARE
  4. More Functionality in the :LIBRARY: Assertion Operator
    The assertion operator :LIBRARY: is used to generate shared libraries and has been changed to support different shared library suffixes.
    The syntax of :LIBRARY: now is
        name [major.minor] :LIBRARY: source [required-libraries]
    major.minor would be the version number of shared libraries if the compiler of the machine supports them. required-libraries are the libraries that have to be linked in conjunction with the current target library when the library is in use. The required libraries can be specified as -llibrary_name format. nmake will generate a file called name containing the required libraries information, and install it in $(LIBDIR)/lib directory. For example, if one builds a library, libcs.a, which has to be used in conjunction with libnsl and libsocket, it can be specified as:
        cs 2.0 :LIBRARY: source.c -lnsl -lsocket
    In addition to generating the target library, libcs.a (and if the :ALL: is specified in the makefile, or if the all or install common action is specified on the command line), a file called cs will be generated, which contains the required libraries information:
        -lcs -lnsl -lsocket
    and install it by the install common action to $(LIBDIR)/lib directory. Each time -lcs is specified in makefiles, it automatically expanded to -lcs -lnsl -lsocket. Any required library not found on the current host machine is silently omitted.

2.4 Special Atoms

  1. New .LOCAL Special Atom
    The $(MAKE) command has to be executed on the local machine if coshell is used, so that jobs can be distributed among other idle machines in the LAN. To make sure of this, .LOCAL has to be one of the target's attributes. 2.2 makefiles used .ALWAYS as a work around, which should be changed to .LOCAL. For example:
        t : .LOCAL
    	    $(MAKE) $(=) $(-)
  2. New .FUNCTIONAL syntax
    The arguments of a functional variable are specified as $(%) in the action block and the return value is set by the return statement. For example:
    	    return $(%:T=F)
    The syntax for a functional variable with arguments has been changed from:
        $(var(arg ...))
        $(var arg ...)
  3. New .MAKEDONE Special Atom
    The new special atom .MAKEDONE has been added. The action of .MAKEDONE is executed after the execution of .DONE.
  4. Extended Functionality of .TERMINAL
    The .TERMINAL special atom is asserted to regular files in nmake 2.2; now it can also be asserted to directories that do not have subdirectories. This is used as an optimization in searching directories for binding files when there are many directories and many file names specified with directory prefix:
        .SOURCE.c : src1 src2
        src1 : .TERMINAL
        SRC = subdir/foo.c
        foo :: $(SRC)
    In this example, foo.c will not be searched in src1 directory because src1 does not have sub-directories. The benefit of asserting .TERMINAL to directoies will only be noticeable in large projects.
  5. .SCANNED Can Be Removed
    This special atom can be removed from files being scanned by an assertion such as,
        a.c : -SCANNED
    This will cause rescan the files at a later time.

2.5 Edit Operators

  1. Extended Functionality of Edit Operator :A
    This edit operator can return the selected target tokens with specific prerequisites or attributes. The syntax now is :A[!]=expression, where expression can now be either attributes or prerequisites:
        TARGETS = a b c
        a : x y
        b : y z
        c : x z
    	    : $(TARGET:A=y)
        : a b
  2. New Edit Operator :F=V
    :F=V a string is converted to be the valid nmake variable name. For example, if STRING=S$T*U:
    would give S.T.U. The invalid variable name characters (i.e. "$" and "*") are converted to the valid character ".".
  3. Changed Functionality of Edit Operator :G
    :G now returns file names that can be generated to match the specified metarule pattern. For example:
        FILES = g.sch main.c
        %.c c_%.c %.h: %.sch
    	    cat  $(>) > $(>:B:S=.c)
    	    echo "#include '$(>:B).h'" > c_$(>:B:S=.c)
    	    cat $(>) >> c_$(>:B:S=.c)
    	    echo "#define $(>:B)_x 1" >$(>:B:S=.h)
    	    : $(FILES:G=%.h)
    	    : $(FILES:G=%.o)
    	    : $(FILES:G!=%.h)
    The output is:
        + : g.h
        + : g.o c_g.o main.o
        + : main.c
    where g.h can be generated from g.sch, g.o, c_g.o and main.o are the files that can be generated from the files listed in $(FILES), and main.c is the file that cannot generated a .h file.
  4. Extended Functionality of Edit Operator :H
    :H<= gives a low-to-high numeric sort, and :H>= gives a high-to-low numeric sort. :H[<>][=]U gives a unique sorted list:
        V1 = 1 2 3
        V2 = 1 2 4
        V3 = $(V1) $(V2)
        t :
    	    : $(V3:H<=U)
        : 1 2 3 4
  5. New Edit Operator :K=[pfx]
    This operator acts like xargs(1) and splits long lines into separate token group, and prepends the optional pfx to each group of tokens:
        LIST = <a_long_list>
        t :
        echo <the_first_block_of_the_list>
        echo <the_second_block_of_the_list>
        echo <the_last_block_of_the_list>
  6. Extended Functionality of Edit Operator :O
    :O gives the number count of tokens, and :O! gives the string length of each token:
        FILES= a bb c
        t :
    	    : $(FILES:O) 
    	    : $(FILES:O!)
        : 3
        : 1 2 1
  7. New Edit Operator :P=A
    This operator gives the absolute path name for files specified:
        FILE = a.c
    	    : $(FILE:P=A)
    if the file a.c is in the current directory /home/test, then the output will be:
        : /home/test/a.c
  8. New Edit Operator :P=H[=suffix]
    This operator generates 9-character hash file names (or up to 14 characters if suffix is used) for the given token:
        FILE = a.c
        t :
    	    : $(FILE:P=H=.hash)
        : ME707F6A4.hash
  9. Extended Functionality of Edit Operator :P=L
    :P=L* returns all views of a bound file, and :P=L! returns the first occurrence of a bound file from all the views. For example, assume the VPATH=/n1:/n2:/n3, and a.c exists in /n1 and /n2, and b.c exists in /n2 and /n3:
        SRC = a.c b.c
    	    : $(SRC:P=L*)
    	    : $(SRC:P=L!)	
        : /n1/a.c /n2/a.c /n2/b.c /n3/b.c
        : /n1.a.c /n2/b.c
  10. New Edit Operator :T=M
    :T=M generates the parentage chain of each active token:
        t : a.x
        a.x : a.z
        a.z : 
    	    : $(<:T=M)
        : t a.x a.z
  11. New Edit Operator :T=O
    :T=O[-][+][=data] complements :T=I[-] to give output:
        IFILES = in.list 	/* contains: main.c a.c b.c c.c */
        OFILE = out.list
        t :
  12. New Edit Operator :VP and :VA
    See "Auxiliary Values and Variables" in Section 2.1.1.

2.6 Scan Rules

  1. Non-Line-Oriented Scan Rule
    nmake 3.0 introduces the notation of @ for repeated patterns in scan rules:
        .SCAN.4gl : .SCAN
    	    I| include @ "%"|
    	    I| global @ "%" @ endglobal|
    this scan rule can scan source lines such as:
        include "a" "b" "c"
  2. New Function .INCLUDE. for Flags
    In nmake, the function .INCLUDE. is written for generating the flags for locating included files of specified languages. It takes the form of
        $(.INCLUDE. <lang> <flag>)
    For example, to generate flags for awk scripts:
        AWKFLAGS += $$(.INCLUDE. awk -I)

2.7 Enhancement in cpp

  1. New cpp Options
    -Aarg has been added for SVR4 assertions. -D-R is to preprocess for transition mode. -H is to print the included references in stderr. -I-C is to mark any following -Idir as C source. -M is to output the file dependencies in makefile dependency relationship format.
  2. New cpp Pragmas
    The following mentioned pragmas are generated as needed by probe. Here listed is for completeness.
    pp:cdir <dir_list> marks files in dir_list as C source. This is for preprocessing C++ source. For processing C++ source, nmake cpp will put extern C { ... } around C system headers and put extern C++ { ... } around C++ system headers. The new option -I-C and the new pragma pp:cdir are added for handling this.
    pp:elseif allows non-standard #else if, #else ifdef, and #else ifndef directives.
    pp:splicecat has been added to allow newline in macro definitions. This is to make cases such as
        #define a b \
    be handled equivalently to the old (Reiser) cpp handling:
        #define a b /**/ c
    or ANSI cpp handling:
        #define a b ## c

    pp:stringspan allows newline line in a double quoted string.
    pp:transition is to set transition mode.
    pp:truncate [n] is to truncate macro names to n characters if specified, otherwise, to 8 characters. This is for compatibility with non-flexname compilation systems.
  3. New Directives
    #rename has been added to rename an old macro name to a new one.
        #define oldname aaa
        #rename oldname newname

2.8 Enhancement in probe

  1. CC Can Be Set with Particular Options
    Now user can add compiler option(s) to CC so that probe generates a separate configuration file just for the specified option(s). For example, CC = cc -Aa and CC = cc -g will reference different configuration files.
  2. Handling C++'s -l++
    nmake now expands -l++ to a set of libraries to match the expansion done in some C++ language processors. For example, using C++3.0, nmake expands -l++ properly to be -lg2++ -lGA -lGraph -l++ for some C++ language processors. The probe variable CC.REQUIRE.++ generated by probe contains the expanded value.
  3. New Options for <nmake_root>/lib/probe/probe
    probe now has three new options: -d, -D and -t. -d is for deleting the configuration files. -D is for debugging, which shows the steps that probe used in generating the configuration files for the language processor specified. -t is for testing, which generates a new configuration file on stdout without modifying the existing configuration file.
    The general usage is as the following:
        <nmake_root>/lib/probe/probe -[dDt] C [make|pp] path_of_compiler
    For example, one can delete the probe configuration files generated for language processors (e.g. compilers) by giving the command of:
        <nmake_root>/lib/probe/probe -d C make path_of_compiler
        <nmake_root>/lib/probe/probe -d C pp path_of_compiler
    To delete the configuration files, one has to be the owner of the files or the owner of the language processor.
  4. New Option -d for <nmake_root>/lib/probe/C/make/probe
    The probe shell script (Note: different probe from the one mentioned in the previous section) can be run standalone in debug mode by using -d flag to examine the steps of probing information for nmake.
        <nmake_root>/lib/probe/C/make/probe -d path_of_compiler
  5. New Option -d for <nmake_root>/lib/probe/C/pp/probe
    The probe shell script (Note: different probe from the ones mentioned in the previous sections) can now be run standalone in debug mode by using -d flag to examine the steps of probing information for nmake cpp.
        <nmake_root>/lib/probe/C/pp/probe -d path_of_compiler

2.9 Miscellaneous

  1. Rules for Supporting the C++ Ptrepository Feature
    Rules have been added to the default base rules ( to support the Template Instantiation feature in C++ release 3.0. The CC.DIALECT in the probe configuration file will contain PTREPOSITORY. The special atom .SOURCE.ptr can be used to specify directory name other than ptrepository. If .SOURCE.ptr is not specified in a makefile, nmake searches the ptrepository directory.
  2. Archive Format
    Users can specify ARSCAN (default to "ar"), ARSCANFLAGS (default to "tv"), and RANLIB (default to ranlib) in the project-wide rules for unusual archive formats.
    nmake now handles archive member file names with >= 15 characters, and also support AIX archive format.
  3. New Syntax for Library Link Flag
    The new library link flag +llibrary_name has been added for selective static linking. If this flag is specified, nmake will try to bind the archive library first.
        t :: main.c -la +lb
    where libb.a will be linked even if the shared version of the library (e.g.,*) exists in the same directory. Please recall that -la will cause to link the shared library first.
  4. User-defined Attributes Name
    User-defined attribute names are no longer required to start with dot (".").
  5. Searching for User-defined Operators
    User-defined operators can be specified in a separate file called where op is the operator's name, and the file can be placed in the <nmake_install_root>/lib/make directory. For example:
        t :MYOP: a b c
    The user-defined operator rule, :MYOP: can be specified in a file called and the file can be placed in <nmake_install_root>/lib/make directory. In this way, user can provide additional rules to the base rules without modifying the base rule file (e.g.,
  6. Enhancement in Documentation
    The "nmake User's Reference Guide" has been revised. The index has been augmented considerably. Scan rules have newly been documented as the Appendix G.

3. Changes Impacting 2.2 Makefiles

3.1 Changes in Variables

  1. Engine Variable MAKEBUFFERSIZE Has Been Deleted.
    now dynamically allocates buffer space.
  2. Change in Default Value of RMFLAGS.
    The default value of RMFLAGS has been changed from -rf to -f.

3.2 Changes in Assertion Operators

  1. The Variable Expansion Time Changed in :IDENTIFIER: Assertion Operators.
    The variables used in the target and prerequisite positions of the :IDENTIFIER: assertion operator will be expanded at compile time instead of at execution time. For example:
        Tmps = $$(!$(TSPEC):N=*.tbl:B:S=.tmp)
        $(GENHDRS) $(Tmps) :JOINT: $(TSPEC)
    To have this 2.2 makefile work in 3.0, $(Tmps) has to be changed to $$(Tmps).
    Another example of this is:
        $$(LBINDIR) :INSTALLDIR: pgm
        LBINDIR = $(INSTALLROOT)/lbin
    has to be changed to:
        LBINDIR = $(INSTALLROOT)/lbin
        $(LBINDIR) :INSTALLDIR: pgm
    so that $(LBINDIR) will have the desired value at the makefile compile time.
  2. :INSTALLDIR: Now Makes Directories to Any Depth
    :INSTALLDIR: now makes the directory specified on the lhs of the operator to the depth as specified. For example,
        $(INCLUDEDIR)/subA/suba :INSTALLDIR: myfile
    Here, make the directories of $(INCLUDEDIR), $(INCLUDEDIR/subA, and $(INCLUDEDIR)/subA/suba, if those directories don't exist at installation time.
  3. Changes file permissions in :INSTALLDIR:
    The syntax of change file permissions at installation by using :INSTALLDIR: is changed. The new syntax is
        $(BINDIR) :INSTALLDIR: user=root group=adm mode=4755 file1
    where user= is for changing user ID, group= is for, changing group ID, and mode= is for changing permissions of the file.
  4. :LIBRARY: Only Makes .a by Default
    :LIBRARY: makes .a only by default, even if CCFLAGS+=$$(CC.PIC) is on. To make a shared library, one has to have :ALL: in the beginning of the makefile, or give the all or the install common action on the command line.
  5. Output Format of :COMMAND:
    changes the blank space to a new-line ("\n") character after each shell output to the lhs variable of :COMMAND:. For example,
        LIST :COMMAND:
    	    echo A
    	    echo B
    The content of LIST was "A B" in 2.2, but now is "A\nB". If one wants to change the new-line character to be a space, one has to edit the variable by using edit operator :C. For example:

3.3 Changes in Command Line Options

  1. -H (headerstate)
    The Command line Option headerstate (-H) has been deleted.
  2. -x (expandview)
    A new option expandview (-x) has been added. The expandview command line option should be used when using the 3DFS(tm) on the main machine and using coshell to access non-3D machines. The expandview option forces to generate full path names for viewpathing.
  3. -M (mam)
    The -M used with -k (keepgoing) and -x (expandview) causes to generate different output. This may be necessary under certain circumstances. See Section 4.4.3 for details.
  4. User-defined Options
    The definition and usage of a user-defined option, option, have been changed. The definition of the option is now
        -o option=<flag>,<name>[,<type>,<function>]
    The flag is the option flag that can be used on the command line associated with - or +. (e.g. -u); the name is the option name that can be used with -o (e.g. -o unconditional); the type is the type of the option, which must be one of b (boolean), s (string), or n (numeric); function is the function name in the Makefile which acts on the value assigned to the option name, given:
        .set.opt: .FUNCTION
    	    set $(%:/0/no/:/1//)force
        set option=u,unconditional,b,.set.opt
    the usage is either
        nmake -u
        nmake -o unconditional
    In this example, the flag of the user-defined option is u; the name is unconditional; and the type is boolean; the function name is .set.opt. When the option is used, the function .set.opt will be invoked. In this example, the function sets force or noforce option, depending on whether the user-defined option is used or not.
    nmake now also passes the user-defined options to $(-) and $(+).

3.4 Changes in Special Atoms

  1. The special atoms .UNTOUCH, .MAKEPPFLAGS, .MAKEPREREQ, .MAKESCAN, and .PRECIOUS have been deleted.
  2. The special atom .TOUCH has been replaced by .REBIND. The special atom .REBIND supports targets generated in .SOURCE directories.
  3. The special atom .DEBUG now is aliased to .QUERY.
  4. The action of special atom .DONE is now saved in the state files.

3.5 Changes in Edit Operators

  1. :M now uses the egrep pattern matching scheme. For example:
        STRING = abcd 1234 efgh 5678
        SOMEFILE = $(STRING:M=.*[cf8].*)

3.6 Changes in Scan Rules

  1. $(.SCAN.)
    $(%) instead of $(.SCAN.) is used in SCAN syntax M (map).
    For example, in the following INFORMIX 4gl scan rules:
        .SCAN.4gl : .SCAN
    	    I| globals '%' |A.4GL.INCLUDE|
    	    I| globals "%" |A.4GL.INCLUDE|
    	    I| GLOBALS '%' |A.4GL.INCLUDE|
    	    I| GLOBALS "%" |A.4GL.INCLUDE|
    	    I| # FORMDEF '%' |M$$(.SCAN.:/.*/&.frm/)|
    	    I| # formdef '%' |M$$(.SCAN.:/.*/&.frm/)|
    	    I| # FORMDEF "%" |M$$(.SCAN.:/.*/&.frm/)|
    	    I| # formdef "%" |M$$(.SCAN.:/.*/&.frm/)|
    the last four lines must be changed to:
    	    I| # FORMDEF '%' |M$$(%:/.*/&.frm/)|
    	    I| # formdef '%' |M$$(%:/.*/&.frm/)|
    	    I| # FORMDEF "%" |M$$(%:/.*/&.frm/)|
    	    I| # formdef "%" |M$$(%:/.*/&.frm/)|
    Scanrules are now documented in detail in Appendix G of nmake User's Reference Guide.
  2. Moved $include from .SCAN.F to .SCAN.sql
    The file including format, $include, has been moved from .SCAN.F to .SCAN.sql. If one used .SCAN.F for searching $include, .SCAN.sql should be used for the purpose.

3.7 Changes in cpp

  1. Changes in Option -D
    The notation of -D"#define A a" of cpp has changed to -D"%define A a".
  2. Change in Option -D-M
    By default, 3.0 cpp includes files as they are seen. The meaning of option -D-M is to include files just one time. Files with #pragma pp:multiple on the first line will be included multiple times even if -D-M flag is on.
  3. Change in Option -D-D
    -D-Q replaces -D-D to produce checkpoint dump.
  4. Change in Option -D-dlevel
    -D-dlevel option now is -D-Dlevel to set debugging trace.
  5. Deleted Options -D-K and -D-Q
    -D-K and -D-Q options have been deleted.
  6. Change in Pragma pp:map
    The directive mapping format, %, has been removed. A new scheme of mapping has been added. The format is,
        #pragma pp:map "matching pattern" "editing expression"
    For example:
        #pragma pp:map "/#c_include>/" "/#c_include(.*)/__C_INCLUDE__(1)/"
        #define __C_INCLUDE__(x) #include x
    This example maps the #c_include directive to be a #include directive.
    If one used #pragma pp:map in C source code or modified in probe configuration files, one should change them to the new format.
  7. Deleted Pragmas
    pp:hosted, pp:keyword, pp:passthrough, and pp:quote pragmas have been deleted.

3.8 Change in probe Output

  1. Variable CC.PATH has been changed to CC.CC.

3.9 Changes in coshell

  1. coshell is the network shell coprocess server
    It can establish shell coprocesses to machines producing compatible executables on the local area network and send user jobs to these shells. If coshell is not present in <nmake_install_root>/bin, coshell is not supported for your environment.
  2. ksh version
    The ksh version 11/16/88i (or later) is absolutely required when using coshell. The command what $(whence ksh) should return this version as its output. The SHELL environment variable needs to be set to the ksh 11/16/88i (or later) version for coshell to work.
  3. .profile and $ENV
    The environment of remote shells is initialized by .profile and $ENV. Interactive queries within .profile and $ENV must be disabled for non-interactive shells; otherwise coshell will fail:
        case $- in
    The following variables are set up by coshell and can be referenced in .profile: HOSTNAME, HOSTTYPE, COTEMP.
  4. Generating the Local Host Attribute File
    Local host attribute file contains the names of all the machines that are available in the local area network along with some other pertinent information. The file local.ast provided with the distributed nmake software package (located in <nmake_install_root>/share/lib/cs) is an example.
    Two shell scripts, genlocal and genshare, are provided with the distributed nmake software package; they are located in <nmake_install_root>/bin and can be used to generate the local host attribute file. The local host attribute file is shared by all the coshell users. It should be manually updated as hosts are added to or deleted from the local network.
    The genshare script is run first to generate information on servers for the network. By default, this information is stored in <nmake_install_root>/lib/cs/share. After this information has been stored, the genlocal script is run to generate the local host attribute file. By default, this information is stored in <nmake_install_root>/share/lib/cs/local.
    If the share file generated by the genshare script is not stored in the default path, you must pass its path to the genlocal script using the -f option. For example,
        genlocal -f path_to_share_file
    You may modify the generated files to meet your needs.
    Please note: coshell requires that the directory <nmake_install_root>/share be at the same location on all the hosts specified in the local file.
    The <nmake_install_root>/bin/ss command displays host status information.
  5. Starting coshell
    A ksh function cosh is included in the nmake software package to start/quit coshell. This function resides in the <nmake_install_root>/fun directory. You may access it by including this directory in your FPATH environment variable. cosh starts coshell, cosh -Q kills the coshell server and appends the output of the date and the coshell -t -sl -Q commands to $HOME/.cosh.
    This function also adds the word 'coshell' to the title bar of the window which the coshell server is started. The environment variable NPROC is set to 10. The nmake -j command line option takes precedence over the NPROC environment variable. In addition, the environment variable COSHELL is set to coshell.
    The value of NPROC can be set to a higher number, and the resulting number of concurrent jobs can be based on the values of the percpu, peruser, perserver, and maxload coshell global attributes. (Please see coshell(1) for details).
    coshell uses /tmp to write files. If /tmp is mounted as a swap file system, coshell does not work due to a /tmp bug. To work around this, an environment variable CS_MOUNT_LOCAL needs to be set to another file system where the user has read and write permissions. For example:
        export CS_MOUNT_LOCAL=$nmake_install_root/tmp

    Files under <nmake_install_root>/share/lib/ss are generated after coshell starts. Each host entry in <nmake_install_root>/share/lib/cs/local has a file of the same name as the host in this directory. For efficiency the system status of the host is compressed into 8 bytes and stored in the time stamp field of each file status and the status is updated every minute. If the contents of <nmake_install_root>/share/lib/cs/local gets changed, the deleted host names should be removed from the <nmake_install_root>/share/lib/ss directory.
  6. Tips on Taking Advantage of coshell

3.10 Miscellaneous

  1. Change in Metarule Processing
    nmake now supports metarules with multiple rhs patterns:
        %.o : 
  2. Changes in Output
    Two output changes are listed below:
  3. nmake Won't Create the .mo File in the Top View
    When using viewpathing, nmake now won't drop the .mo file into the top view if the lower level *.mo is up to date.
  4. Main Target Needed in Makefiles
    If there is no main target in a makefile, the probe configuration file name was the prerequisite of .MAIN in 2.2. Now an error message is displayed to notify the user.

4. Bug Fixes

The following bugs were fixed in nmake 3.0:

4.1 Fixes in Handling Variables

  1. A Fix in the += Assignment Operator
    Do not accumulate extra spaces when null value variables are on the rhs of the += assignment operator.
  2. Fixes in Handling Automatic Variables
  3. Fix in Handling Modified Variable Value
    If the value of a variable is a bound file name and it may be changed at execution time especially under viewpathing, now examines the old value when nmake command is invoked the second time. If the value changed, makefile will be re-compiled:
        DEFAULT_SRCS = $("file":T=F)
    	    : $(DEFAULT_SRCS)
    When nmake command runs for the first time, the VPATH is set and "file" is located in a lower view. When nmake is invoked the second time, the VPATH is not set, "file" does not exist. nmake will now re-evaluate the value for DEFAULT_SRCS.
  4. 4.1.4 A Fix in Base Rule Variable link
    now correct pattern matching for link=pattern (except link=* in viewpathing, see Section 5.1 for details) when installing selective targets by link (i.e., ln). For example, if t1, t2 and t3 are targets:
        nmake install link=t1
    t1 will be linked to the installed area, and the targets t2 and t3 will be copied.
  5. A Fix in Handling $PATH
    Able to handle the long length of the environment variable PATH value.

4.2 Fixes in Handling Common Actions

  1. Fixes in clobber
  2. A Fix in clobber.install
    When INSTALLROOT=., clobber.install will now remove files in the installed area.
  3. Fixes in clean and clobber
    The clean and clobber common actions will not remove the files in the installed area when INSTALLROOT has the value of $(HOME).

4.3 Fixes in Handling Assertion Operators

  1. A Fix in :LIBRARY:
    :LIBRARY: now will take CCFLAGS assignment from the command line. For example, using :LIBRARY: with CCFLAGS+=-g on the command line now generates the correct library name (e.g. libname-g.a).
  2. Fixes in the :JOINT: Assertion Operator
    Now make the multiple targets specified on the lhs behave the same when common actions are applied. Touching any secondary targets of a multiple targets assertion now will trigger the action. :JOINT: will not cause core-dump at the subsequent nmake invocation.
  3. Fixes in :MAKE:
    Now find makefiles specified on the rhs of the :MAKE: assertion operator via viewpathing. Also, the variable values assigned on the command line are correctly passed to makefiles. In addition, treats the lhs atom as a label target.
  4. Fixes in :cc:
    :cc: now inherits .SOURCE.h and can locate header files specified in .SOURCE.h. Also, :cc: works in a viewpathing situation. nmake can use *.o's in a lower view to link with top-view targets.
  5. Fixes in :COPY:
    If an implicit dependency of a copied file of :COPY: is touched, the copied file will now be rebuilt. For example:
        a1.c :COPY: a.c
    If the included header file is touched, both of a.c and a1.c will be rebuilt.
  6. A Fix in :INSTALLDIR:
    nmake won't install the targets such as in the following example where the target name includes a relative or absolute path, and lhs of :INSTALLDIR: is not specified.
        LIBRARIES = ../lib/liba.a
        $(LIBRARIES) :: a.c

4.4 Fixes in Handling Command Line Options

  1. A Fix for the Exit Code of Unknown Command Line Option
    Now give exit code 1 for any unknown command line options.
  2. A Fix for -g
    Now allow both the global makefile and its compiled file (*.mo) to coexist in the same directory.
  3. Fixes for -M
    Fixes were made in the -M command line option to work with -k and -x options to produce correct output for explicit recursion (i.e. $(MAKE)) and implicit recursion (i.e. :MAKE:), nested includes and conditional includes, and in a viewpathing situation. -k is needed when there are nested includes and -x is needed when using viewpathing. Fixes were also made to generate -l++ for the C++ link line. This command line option has to work with keepgoing (-k) and expandview (-x) to get the correct output. (See Section 5.1 also).

4.5 Fixes in Handling Special Atoms

  1. A Fix in the .DONTCARE Special Atom
    Now correctly react to the command line options ignore and keepgoing when the .DONTCARE special atom is used.
  2. A Fix in the .UNBIND Special Atom
    Now correctly unbind the directories. This special atom didn't function in nmake 2.2.
  3. A Fix in .APPEND.%.x
    .APPEND.%.x now works where x is .ARCHIVE or .TARGET.

4.6 Fixes in Scanning

  1. A Fix in Scanning for C Conditional Includes
    Touching any conditional included header files causes rebuilding relevant target(s).
  2. A Fix in Scanning for Makefile Includes
    Recompile makefiles when an included file of the makefile is touched.

4.7 Fixes in Viewpathing

  1. A Fix in Handling Directory Structure in Viewpathing
    Now correctly find files when some directories are missing either in the top view, or in the intermediate view, or in the bottom view.

4.8 Fixes in Handling Metarules

  1. A Fix in Metarule Chaining
    Now work properly on metarule chaining. Cases like the following did not work in nmake 2.2. : %.o
    	    cp $(*) $(<)
        %.y : %.r
    	    cp $(*) $(<)
        %.r : %.m
    	    cp $(*) $(<)
    In this example, nmake makes from y.m by triggering a chain of metarules defined in this makefile and in the base rule file.
  2. A Fix in %.o : %.c .CLEAR Metarule
    Now do not recompile everything when the user is in the top view of VPATH and the rule of
        %.o : %.c .CLEAR
    is set in a lower view.

4.9 Fixes in Programming Constructs

  1. A Fix in if-elif-else-end Construct
    The construct with back slashes in elif clause now works properly.

4.10 Fixes in cpp

  1. Now correctly processes the ## C++ notation for concatenation.
  2. Does not generate extra space for asm.
  3. Will no longer dump core when handling long comments in C code.
  4. Now gives more appropriate error messages when an error is detected.
  5. Now handles a macro definition containing # at the beginning of the string.

4.11 Fixes in probe

  1. Now generates correct configuration files for all the compilers we know of.
  2. Generates correct directory names for standard include files and libraries of the C++ language processor.

4.12 Fixes in ccc

  1. ccc generates the -I-D option correctly when the mcc68k cross-compiler is used on a SUN4 workstation with nmake.
  2. ccc can now recognize source with .C suffix.

4.13 Miscellaneous

  1. Linking Shared Libraries Once and Not Relinking
    No longer relinks a newer version of shared libraries to targets after the first link, unless the base rule variable force_shared is set to 1.
  2. A Fix in Generating -L Flags
    Now generates -L for the libraries specified in LDLIBRARIES and for shared libraries specified as -lname (i.e. library name is libname.a) in the prerequisite list of the :: operator.
  3. A Fix in Linking Library of -l*.1
    Now treats -l*.1 correctly as a library, not a man page.
  4. Changing User-defined Attributes
    Now do not dump core when user-defined attributes are changed or deleted.
  5. A Fix in the # Style Comments
    Now correctly recognize # style comments when an odd number of quotes exists in the comment.
  6. A Fix in Binding
    No longer dumps core when it cannot bind a file.
  7. A Fix in Handling ./ File Name Aliasing
    Now work correctly with ./ file name aliasing. For example:
        t :: ./src/main.c
        t :: src/main.c
  8. A Fix in Handling exec make
    When nmake execs old make, the Makefile is now picked, not makefile.
  9. A Fix in Generating -I Flags
    Now generate the correct -I compiler flags and no longer ignores the /usr/include used in the .SOURCE.h special atom.
  10. A Fix in Handling cpp
    When using nohup, nmake now won't pick up a wrong cpp.
  11. A Fix in the 2.2 Release Notes
    The base rule variable concurrency has been replaced by recurse.
  12. Fixes in nmake man Pages
    Man pages have been updated.

5. Known Bugs and Remarks

5.1 Known Bugs

The following is a list of known bugs:

5.2 Remarks

The followings are some remarks:

6. Conclusion

nmake 3.0 release has expanded the software capabilities. Current nmake 2.2 customers under maintenance will be entitled to this 3.0 release at no charge. Information on purchasing nmake 3.0 licenses can be obtained through the nmake hotline - (908)-582-5880.

Last Update: Friday,12-Aug-2016 12:28:51 EDT