We are pleased to announce availability of Alcatel-Lucent nmake 12. nmake 12 provides several features and enhancements, including the following:
- Capture of Triggered Target Explain Data
- New Variable Edit Operators to Access Explain Data
- Long --name Style Options
- New --version Command Line Option
The release is compatible with Javadeps alu2.2.5 and nmake Eclipse CDT plugin 0.5.0, both separately downloadable. See the nmake 12 Release Notes for more information including a complete list of changes from the nmake 11 release.
Most of us have run an incremental build and then wondered why something
rebuilt that wasn't expected. nmake has always supported the
-e) option to show explanations for
its actions, however most folks don't run all their builds with the
explain option enabled and sometimes you don't realize
you need it until after a build is done.
A new feature has been introduced in nmake 12 that captures the explain data in the nmake statefile. Now the explain messages can be retrieved after a build is complete without using the explain option to run the build. The data is also associated with the affected targets which provides more context than the typical explain output.
In the following example two targets are built and each source file includes
its own header file. The makefile has been built once and is up to date.
a.h and rebuild.
$ cat Makefile CC = gcc .SOURCE.h : include :ALL: abc :: a.c b.c c.c xyz :: x.c y.c z.c $ touch include/a.h $ nmake + gcc -O -Iinclude -I- -c a.c + gcc -O -o abc a.o b.o c.o + gcc -O -Iinclude -I- -c z.c + gcc -O -o xyz x.o y.o z.o
Oh no, why was z.c compiled? Now we can dump the explain messages from the statefile using the list and explain options along with the file option to specify the statefile instead of the makefile.
$ nmake -lef Makefile.ms /* Explain */ a.o : include/a.h [Aug 18 14:44:14 2010] has changed [Aug 18 14:40:50 2010] abc : include/a.h [Aug 18 14:44:14 2010] has changed [Aug 18 14:40:50 2010] z.o : include/a.h [Aug 18 14:44:14 2010] has changed [Aug 18 14:40:50 2010] xyz : include/a.h [Aug 18 14:44:14 2010] has changed [Aug 18 14:40:50 2010]
xyz were updated because
a.h changed. It looks like we forgot
This feature allows you to retroactively get the explain data for the
last build. In a build where nothing is updated the explain dump will
be empty. This feature is controlled by the explainlog
option and is enabled by default. To disable it use
Variable Edit Operators
The explain data can be referenced in a makefile using new variable edit
operators. This allows your own custom rules to output or collect the data.
The variable edit operators are not affected by the
|$(VAR:T=QE)||Query the Explain Message. Returns the explain message, if it has been set, for each token in a useful presentation format, otherwise returns null. Typically the explain message is set for targets that have been triggered.|
|$(VAR:T=QEU)||Query the Unformatted Explain Data. Returns the raw explain data, if it has been set, for each token, otherwise returns null. Same as QE but the message is returned in a compact fielded format allowing easy extraction of data using standard nmake tokenization operations.|
|$(VAR:F=%(explain)S)||Formats the raw explain data in a useful presentation format.|
The following makefile shows a custom metarule using the
edit operator to output the reason the current target was triggered.
Again the makefile is up to date and we run an incremental build.
$ cat Makefile %.o : %.c (CC) (CCFLAGS) silent echo reason: $(<:Q) - $(<:T=QE:Q) $(CC) $(CCFLAGS) -c $(>) CC = gcc .SOURCE.h : include :ALL: abc :: a.c b.c c.c xyz :: x.c y.c z.c $ touch include/b.h $ touch x.c $ rm z.o $ nmake reason: b.o - include/b.h [Aug 18 15:51:37 2010] has changed [Aug 18 14:40:17 2010] + gcc -O -Iinclude -I- -c b.c + gcc -O -o abc a.o b.o c.o reason: x.o - x.c [Aug 18 15:51:41 2010] has changed [Aug 18 14:39:33 2010] + gcc -O -Iinclude -I- -c x.c reason: z.o - z.o [not found] has changed [Aug 18 15:51:08 2010] + gcc -O -Iinclude -I- -c z.c + gcc -O -o xyz x.o y.o z.o
The next example changes the makefile slightly to capture the unformatted
explain data with the
:T=QEU edit operator. The unformatted
data is in a fielded format that can be easily parsed and used with local
scripts and tools.
$ cat Makefile %.o : %.c (CC) (CCFLAGS) silent echo reason: $(<:Q) - $(<:T=QEU:Q) $(CC) $(CCFLAGS) -c $(>) CC = gcc .SOURCE.h : include :ALL: abc :: a.c b.c c.c xyz :: x.c y.c z.c $ touch a.c $ nmake reason: a.o - "6 a.c 1282161524 1282161287" + gcc -O -Iinclude -I- -c a.c + gcc -O -o abc a.o b.o c.o
The first field is an integer reason code, in this case code 6. The remaining
fields are parameters for this specific explain message. The code numbers
and corresponding messages can be looked up in the file
nmake_install_root/lib/make/explain.map. The message
parameters are shown as %s for a string and
%t for a time stamp.
$ grep ^6 nmake_install_root/lib/make/explain.map 6 %s [%t] has changed [%t]
Here we see the first parameter for reason 6 is a string, in our case "a.c".
And the remaining two parameters are time stamps recorded in seconds from
epoch. Local tools can parse the data and use
to format the messages. The new
:F=%(explain)S edit operator
can also be used to format the unformatted data. Here is a one-liner:
$ nmake -n -f - . 'print $("6 a.c 1282161524 1282161287":@F=%(explain)S)' a.c [Aug 18 15:58:44 2010] has changed [Aug 18 15:54:47 2010]
For more examples and information see the nmake 12 release notes. The explain data is also captured by default in the structured build logs created with the xmakelog command and included in the web build logs generated with the buildlog2html command. See the Build Log documentation for details.
If you are new to nmake but have used other build tools you might be surprised to see a warning that a file has gotten older. For example:
$ nmake make: warning: hello.c has been replaced by an older version + gcc -O -I- -c /home/richb/newsletter/n35/v3/hello.c + gcc -O -o hello hello.o
What does this mean? Unlike other build tools nmake does not simply compare time stamps and check if the prerequisite is newer than the target to trigger an update. The time stamps of the files are stored in the nmake statefile (eg. Makefile.ms). The current time stamps are compared with the time stamps from the statefile so nmake can tell if any of the files have changed since the previous build. If a file's current time stamp is older than the time stamp in the statefile nmake issues the warning and updates the affected targets.
The warning message is issued because it is fairly unusual for the time stamp to go backwards and may indicate a configuration error or another problem in the environment. One possible cause could be a change to the viewpath, such as removing a node from the viewpath so older files are seen or adding a node with older files in front of other nodes. If the warning is for system headers or libraries then perhaps the previous build was on a different machine running a different version of the OS.
There is also a known issue that may cause this warning when the first
prerequisite file of a
:: assertion is also the prerequisite of
:cc: assertion that comes before the
:: in the
makefile. To work around this issue move the
to come after
:: in the makefile.
We are interested in any feedback you might have about nmake. Please send comments / suggestions to email@example.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 firstname.lastname@example.org. Thanks for your support!