This new feature provides enhanced build diagnostics by capturing the reason
each target is triggered for an update. "Explain" data is recorded in the
state files and structured build logs
to provide reasons describing why certain actions were taken during the
build as seen in output when using the explain
-e) option. Explanations can be retrieved
after a build is complete whether or not the explain option
was used and are associated with the triggered target
to give more meaning than the standard explain option.
Accessing the explain data for a completed build provides useful
diagnostics, such as determining the cause of unexpected rebuilds, without
manually tracing dependencies or reproducing the build which can be time
consuming and error prone.
The feature is controlled by the new explainlog option. By default the option is enabled and explain data is recorded in the state file. Use the --noexplainlog form to disable the feature and exclude the data from the state file. Note that disabling the feature does not affect the structured build logs nor the new variable edit operators (see New Variable Edit Operators to Access Explain Data), it only affects the state files.
To dump the explain information from a state file use the list
-l) and explain (
-e) options and
specify the state file with the file (
In the following example a header file changed causing the object and
executable to be updated.
$ nmake -lef Makefile.ms /* Explain */ hello : include/hello.h [Jun 10 10:58:36 2010] has changed [Jun 10 10:42:23 2010] hello.o : include/hello.h [Jun 10 10:58:36 2010] has changed [Jun 10 10:42:23 2010]
Explain data is captured by default in structured build logs created using
Capture of explain data is controlled by the
variable. See the
Structured Build Logs Overview
for more information about the handling of explain data in structured build
logs. HTML build logs generated from the structured logs by
include the reason in the target's attribute table.
The following figure shows the above
hello.o target in the
lib/make/explain.mapis included in the nmake distribution to show the mapping of numeric codes to the corresponding message and parameter fields, where
%sindicates a string field and
%ta time stamp field.
Three new variable edit operators are available to access and format explain data during a build.
|$(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 simple example shows the output from the three edit operators.
In this example a header was touched causing the target to update. Notice
:F=%(explain)S operator formats the coded string from
$ cat Makefile CC = gcc TARGETS = hello .SOURCE.h : include hello :: hello.c .DONE : .MAKE print :T=QE - $(TARGETS:T=QE) print :T=QEU - $(TARGETS:T=QEU) print :F=%(explain)S - $(TARGETS:T=QEU:F=%(explain)S) $ nmake + gcc -O -Iinclude -I- -c hello.c + gcc -O -o hello hello.o :T=QE - include/hello.h [Jun 11 14:07:13 2010] has changed [Jun 11 14:06:04 2010] :T=QEU - "6 include/hello.h 1276279633 1276279564" :F=%(explain)S - include/hello.h [Jun 11 14:07:13 2010] has changed [Jun 11 14:06:04 2010]
The next example shows how to use for-loops to access each field of the
unformatted explain data from multiple targets. Note that
lib/make/explain.map in the nmake distribution can
be used to map the first field code number to the corresponding message.
$ cat Makefile CC = gcc TARGETS = hello aloha .SOURCE.h : include :ALL: hello :: hello.c aloha :: aloha.c .DONE : .MAKE local msg field for msg $(TARGETS:T=QEU) print msg: $(msg) for field $(msg) print fld: $(field) end end $ nmake + gcc -O -Iinclude -I- -c hello.c + gcc -O -o hello hello.o + gcc -O -I- -c aloha.c + gcc -O -o aloha aloha.o msg: 6 include/hello.h 1276281965 1276281904 fld: 6 fld: include/hello.h fld: 1276281965 fld: 1276281904 msg: 6 aloha.c 1276281965 1276281904 fld: 6 fld: aloha.c fld: 1276281965 fld: 1276281904
Long command line options are now supported. Long options use the existing option names preceded by -- (dash dash) and take the form --[no]name[=value], where name is the option name, value is an additional parameter used by some options, and no negates the option. The table below shows the long form of some of the more common options. For a full list of options see the nmake(1) man page or Reference Manual.
|short option||long option||description|
|-d level||--debug=level||Provide debug trace output at the specified level.|
|-e||--explain||Print explanation for actions taken.|
|-f makefile||--file=makefile||Read the specified makefile or state file.|
|-F||--force||Force all active targets to be out of date.|
|-g makefile||--global=makefile||Read the specified global makefile.|
|-k||--keepgoing||Continue working if the shell action for the current target returns an error.|
|-j level||--jobs=level||Execute up to level concurrent jobs.|
The --version command line option is now supported to print the version string and exit. There is no short option form.
$ nmake --version Alcatel-Lucent (Bell Labs) nmake 12 06/09/2010