Nokia nmake Product Builder
Customer Support Newsletter

http://nmake.alcatel-lucent.com/newsletters/

Issue No. 45 - December 2013
Contacts
Articles
  1. The :Q Variable Edit Operator
  2. :T=F Expansion of .MAKE Targets
  3. Feedback and Suggestions

The :Q Variable Edit Operator

The :Q variable edit operator is used to quote each token of a variable to remove any special meaning to allow interpretation as a literal string. By default it quotes for interpretation by the shell (sh(1)) but nmake 15 introduced options to quote for the :C (changer), :M (regular expression match), and :N (shell file match) edit operators.

The following example shows the :Q operator being used to quote for the shell. Several files have special characters in their file names. The makefile simply does ls -l on the files. The first run shows what happens when no quoting is used.

$ ls -l
total 0
-rw-r--r-- 1 richb richb 59 Dec  4 15:02 Makefile
-rw-r--r-- 1 richb richb  0 Dec  4 14:00 file&4
-rw-r--r-- 1 richb richb  0 Dec  4 14:00 file;1
-rw-r--r-- 1 richb richb  0 Dec  4 14:00 file<3>
-rw-r--r-- 1 richb richb  0 Dec  4 14:00 file|2

$ cat Makefile
LIST = file;1 file|2 file<3> file&4
targ :
        ls -l $(LIST)

$ nmake
ksh[55]: syntax error at line 9 : `>' unexpected

Note that adding double quotes around $(LIST) will not work because ls will take the list as a single argument.

$ cat Makefile
LIST = file;1 file|2 file<3> file&4
targ :
        ls -l "$(LIST)"

$ nmake
+ ls -l file;1 file|2 file<3> file&4
file;1 file|2 file<3> file&4: No such file or directory
make: *** exit code 2 making targ

Using :Q gives the desired results by quoting each token separately.

$ cat Makefile 
LIST = file;1 file|2 file<3> file&4
targ :
        ls -l $(LIST:Q)

$ nmake
+ ls -l file;1 file|2 file<3> file&4
-rw-r--r--   1 richb    richb          0 Dec  4 14:00 file&4
-rw-r--r--   1 richb    richb          0 Dec  4 14:00 file;1
-rw-r--r--   1 richb    richb          0 Dec  4 14:00 file<3>
-rw-r--r--   1 richb    richb          0 Dec  4 14:00 file|2

For more information we can see how the variable is expanded by using a .MAKE rule.

$ cat Makefile
LIST = file;1 file|2 file<3> file&4
targ : .MAKE
        print $(LIST:Q)

$ nmake
file\;1 file\|2 file\<3\> file\&4

The next example demonstrates quoting for the :C (changer) edit operator. The LNAME function in the makefile returns the main name of each specified library, for example converting libName.a or -lName to Name. $(CC.SUFFIX.ARCHIVE) is a probe variable set to the suffix used for archive libraries which is typically .a on Unix and Linux machines. The string of :C operations first removes -l from the front of the specified name, then removes lib from the front, then removes $(CC.SUFFIX.ARCHIVE) from the end. The first run shows the results without using :Q.

$ cat Makefile
LIBS = libHula.a -lHula

LNAME :FUNCTION:
        return $(%:C/^-l//:C/^lib//:C/$(CC.SUFFIX.ARCHIVE)$//)

targ : 
        : $(LNAME $(LIBS))

$ nmake
+ : Hula Hu

Because . (dot) is a regular expression metacharacter the .a in $(CC.SUFFIX.ARCHIVE) also matches -lHula and trims the end of the name off. By using :Q=C to quote $(CC.SUFFIX.ARCHIVE) for the :C operator we can have nmake treat the . (dot) as a literal to avoid matching anything ending with an a.

$ cat Makefile
LIBS = libHula.a -lHula

LNAME :FUNCTION:
        return $(%:C/^-l//:C/^lib//:C/$(CC.SUFFIX.ARCHIVE:Q=C)$//)

targ : 
        : $(LNAME $(LIBS))

$ nmake
+ : Hula Hula

The :Q=M and :Q=N operators can be used similarly for quoting the :M and :N edit operators respectively.

The :C edit operator uses the regular expression syntax of traditional egrep(1) except the following: newlines are treated as ordinary characters, the ^ and $ characters match the beginning and end of a token respectively, ed(1) style special characters \(, \), \?, \+ and \| are used for the egrep(1) characters (, ), ?, + and |. The \{m,n\} repetition construct is not supported.

The :M regular expression patterns follow the syntax of traditional egrep(1) except the following: newlines are treated as ordinary characters, the ^ and $ characters match the beginning and end of a token respectively. The {m,n} repetition construct is not supported.

The :N shell file match patterns follow the syntax of ksh(1).


:T=F Expansion of .MAKE Targets

Targets with the .MAKE Special Atom in their prerequisite list use nmake statements for their action block. A file for the target is not expected to be generated so if a file is created the :T=F edit operator won't expand the target name and the clobber common action will not remove the file. The following example uses only nmake statements to read infile and output a subset of lines to create targ1. We see the :T=F expansion is null in the .DONE rule.

$ ls -l
total 8
-rw-r--r-- 1 richb richb 123 Dec  4 10:15 Makefile
-rw-r--r-- 1 richb richb 221 Dec  4 10:15 infile

$ cat Makefile
targ1 : .MAKE infile
        local DATA
        read -i $(*) DATA
        print -o $(<) $(DATA:M=;31;:C/$/\n/)

.DONE :
        : T=F [$("targ1":T=F)]

$ cat infile
2013;1;January;31;
2013;2;February;28;
2013;3;March;31;
2013;4;April;30;
2013;5;May;31;
2013;6;June;30;
2013;7;July;31;
2013;8;August;31;
2013;9;September;30;
2013;10;October;31;
2013;11;November;30;
2013;12;December;31;

$ nmake
+ : T=F []

$ ls -l  
total 36
-rw-r--r-- 1 richb richb   123 Dec  4 10:15 Makefile
-rw-r--r-- 1 richb richb  3497 Dec  4 10:21 Makefile.mo
-rw-r--r-- 1 richb richb 19122 Dec  4 10:21 Makefile.ms
-rw-r--r-- 1 richb richb   221 Dec  4 10:15 infile
-rw-r--r-- 1 richb richb   127 Dec  4 10:21 targ1

$ nmake clobber
+ ignore rm -f Makefile.mo Makefile.ms
+ : T=F []

$ ls -l
total 12
-rw-r--r-- 1 richb richb 123 Dec  4 10:15 Makefile
-rw-r--r-- 1 richb richb 221 Dec  4 10:15 infile
-rw-r--r-- 1 richb richb 127 Dec  4 10:21 targ1

Here is a simple technique to use a .MAKE action to generate a file and also have :T=F and clobber behave as might be expected. Give the target a dummy shell action but have the target trigger a separate .MAKE rule that generates the file. The following example was adapted from the makefile above to use this technique.

$ ls -l
total 8
-rw-r--r-- 1 richb richb 170 Dec  4 10:25 Makefile
-rw-r--r-- 1 richb richb 221 Dec  4 10:15 infile

$ cat Makefile 
targ1 : .do.targ1
        : $(<) made

.do.targ1 : .MAKE .BEFORE infile
        local DATA
        read -i $(*) DATA
        print -o $(<<) $(DATA:M=^2013;:C/$/\n/)

.DONE :
        : T=F [$("targ1":T=F)]

$ nmake
+ : targ1 made
+ : T=F [targ1]

$ ls -l
total 36
-rw-r--r-- 1 richb richb   170 Dec  4 10:25 Makefile
-rw-r--r-- 1 richb richb  3537 Dec  4 10:37 Makefile.mo
-rw-r--r-- 1 richb richb 19219 Dec  4 10:37 Makefile.ms
-rw-r--r-- 1 richb richb   221 Dec  4 10:15 infile
-rw-r--r-- 1 richb richb   222 Dec  4 10:37 targ1

$ nmake clobber
+ ignore rm -f targ1 Makefile.mo Makefile.ms
+ : T=F [targ1]

$ ls -l
total 8
-rw-r--r-- 1 richb richb 170 Dec  4 10:25 Makefile
-rw-r--r-- 1 richb richb 221 Dec  4 10:15 infile

Here you can see :T=F expands the target name and clobber removes it.


Feedback and Suggestions

We are interested in any feedback you might have about nmake. Please send comments / suggestions to nmake@alcatel-lucent.com.

We're also open to suggestions for future articles. If there is anything you would like to see in the newsletter please send us a note to nmake@alcatel-lucent.com. Thanks for your support!

<<home / newsletters