Alcatel-Lucent nmake 11 Released
We are pleased to announce availability of Alcatel-Lucent nmake 11. nmake 11 provides several features and enhancements, including the following:
- Refined structured build logs
- New command - buildlog2html
- Enhancements to versioned shared libraries
- W3C conformant time zone designator
- New command - astutil
The release is coordinated with Javadeps alu2.2.5 and nmake Eclipse CDT plugin 0.5.0, both separately downloadable. See the nmake 11 Release Notes for more information including a complete list of changes from the nmake 10 release.
With few exceptions, nmake 11 is upwardly compatible from nmake 10. Current customers may upgrade free of charge to nmake 11 using existing installed licenses, no license upgrade is required. See the nmake 11 release page for download information and documentation, and the Alcatel-Lucent nmake home page at http://www.bell-labs.com/project/nmake/ for general product information.
Javadeps alu2.2.5 Released
Javadeps alu2.2.5 is now available. Javadeps is an optional package and
only required for projects building Java code using the nmake supplied
:JAVA: operator. Download the new package from the
Javadeps page. This release
contains the following fixes:
- string index out of range
- NullPointerException on unreadable directory
nmake Eclipse Plugin 0.5.0
Release 0.5.0 of the experimental nmake
Eclipse Plugin is now available.
This release adds support for Eclipse 3.5 (Galileo) and CDT 6.0.
See the
what's new
page for a detailed list of changes or
visit the nmake Eclipse update site to
upgrade or install the plugin:
http://www.bell-labs.com/project/nmake/download/eclipse
New FAQs
The following new entries have been posted in the FAQ section.
Q: Does nmake use a network license manager or license server?
No, nmake does not use a license manager nor server. The nmake application itself verifies the license key each time it is started. When running nmake on client machines the entire nmake installation tree, including the license file in its normal location in the tree, must be accessible from the client.
Q: Can nmake be run on client machines?
Yes, the nmake license allows a project to run nmake on multiple workstations and servers of the same platform type, subject to licensing terms and conditions. To share nmake to different machines within the project just make the entire nmake installation tree available to the client machines through remote file sharing such as NFS. For example, if nmake is installed under /opt/nmake on a host machine named phoebe, such that the command is /opt/nmake/bin/nmake, then export /opt/nmake on phoebe. The client machines would then NFS mount phoebe:/opt/nmake. It is not necessary to use the same /opt/nmake path on the client as used on host but consistency is recommended to help maintenance and scripting across machines.
The license key may need to be updated to support the client. If the client's IP address does not match an IP address pattern in the host field of the key then a "host not licensed" error will be generated. Contact the Licensing Team to request an update.
Directory Cache - How to pick up generated files
The following problem occasionally comes up: A makefile generates one or more input files that are needed by another rule in the same makefile. The input files are successfully generated but nmake doesn't see the files and gives an error when it goes to make the other rule. This typically happens because nmake caches the contents of directories so it can quickly search the cache instead of rescanning the directory every time it looks for a file. If a rule creates a file that isn't identified as a target to the rule then nmake doesn't know the file has been created. If the file is created after the directory is cached then nmake won't know the file exists and will issue an error when it is needed.
Here is a simple example. The genfiles rule generates two files,
gen1.in and gen2.in which are used to create
targ. You can see the *.in files are generated
but nmake gives an error.
$ ls -l
total 4
-rw-r--r-- 1 richb richb 112 Jul 27 14:02 Makefile
$ cat Makefile
:ALL: genfiles - targ
genfiles : .VIRTUAL
date > gen1.in
uname -a > gen2.in
targ : gen1.in gen2.in
cat $(*) > $(<)
$ nmake
+ date
+ 1> gen1.in
+ uname -a
+ 1> gen2.in
make: don't know how to make .ALL : targ : gen1.in
$ ls -l
total 32
-rw-r--r-- 1 richb richb 112 Jul 27 14:02 Makefile
-rw-r--r-- 1 richb richb 3418 Jul 27 14:05 Makefile.mo
-rw-r--r-- 1 richb richb 18647 Jul 27 14:05 Makefile.ms
-rw-r--r-- 1 richb richb 29 Jul 27 14:05 gen1.in
-rw-r--r-- 1 richb richb 69 Jul 27 14:05 gen2.in
The Better Solution
The best solution to this sort of problem is to properly identify the files as targets to the rule that generates them. In general, any generated files should be identified as targets in the makefile.
Here is a corrected version of the example. The :JOINT:
assertion operator is used because the two *.in targets
are generated jointly, or at the same time. Otherwise nmake would trigger
the rule twice, once to generate each file. Also notice genfiles
is no longer listed as a prerequisite to the :ALL: assertion.
It is not necessary to explicitly trigger the generation of the
*.in files since nmake will trigger those targets when necessary.
$ ls -l
total 4
-rw-r--r-- 1 richb richb 113 Jul 27 14:08 Makefile
$ cat Makefile
:ALL: targ
gen1.in gen2.in :JOINT:
date > gen1.in
uname -a > gen2.in
targ : gen1.in gen2.in
cat $(*) > $(<)
$ nmake
+ date
+ 1> gen1.in
+ uname -a
+ 1> gen2.in
+ cat gen1.in gen2.in
+ 1> targ
$ ls -l
total 36
-rw-r--r-- 1 richb richb 113 Jul 27 14:08 Makefile
-rw-r--r-- 1 richb richb 3455 Jul 27 14:09 Makefile.mo
-rw-r--r-- 1 richb richb 18785 Jul 27 14:09 Makefile.ms
-rw-r--r-- 1 richb richb 29 Jul 27 14:09 gen1.in
-rw-r--r-- 1 richb richb 69 Jul 27 14:09 gen2.in
-rw-r--r-- 1 richb richb 98 Jul 27 14:09 targ
The Better than Nothing Solution
Sometimes generated files just can't be identified as targets in the makefile. In these cases the solution is to have nmake rescan the directory after generating the files to update its cache. A simple rule added to the makefile will do this.
In the following example .SCAN_AGAIN is a prerequisite to the
genfiles rule. The .AFTER special atom in the
.SCAN_AGAIN prerequisite list will cause .SCAN_AGAIN
to be triggered after genfiles completes. The .MAKE
special atom indicates that the action block contains nmake statements an
is not to be sent to the shell. In the .SCAN_AGAIN action
block, -SCANNED removes the .SCANNED attribute on
the directories listed on its left side to get nmake to rescan those
directories. The "." represents the current directory.
A different directory can be listed if the files are somewhere else.
Now, after gen1.in and gen2.in are generated the
directory cache is updated and targ rule is successfully built.
$ ls -l
total 4
-rw-r--r-- 1 richb richb 189 Jul 27 14:27 Makefile
$ cat Makefile
:ALL: genfiles - targ
genfiles : .VIRTUAL .SCAN_AGAIN
date > gen1.in
uname -a > gen2.in
targ : gen1.in gen2.in
cat $(*) > $(<)
.SCAN_AGAIN : .MAKE .AFTER .FORCE .VIRTUAL .REPEAT
. : -SCANNED
$ nmake
+ date
+ 1> gen1.in
+ uname -a
+ 1> gen2.in
+ cat gen1.in gen2.in
+ 1> targ
$ ls -l
total 36
-rw-r--r-- 1 richb richb 189 Jul 27 14:27 Makefile
-rw-r--r-- 1 richb richb 3456 Jul 27 14:34 Makefile.mo
-rw-r--r-- 1 richb richb 18883 Jul 27 14:34 Makefile.ms
-rw-r--r-- 1 richb richb 29 Jul 27 14:34 gen1.in
-rw-r--r-- 1 richb richb 69 Jul 27 14:34 gen2.in
-rw-r--r-- 1 richb richb 98 Jul 27 14:34 targ
Another Solution
Another simple solution is to split up the makefile so the input files are generated by the first makefile and used by the second. An upper makefile will build them in the proper order. The directory cache problem is avoided because the input files already exist when nmake is run on the second makefile. This approach is quite clean and can help provide some organization for complicated makefiles.
In the final example the input files are generated by gen.mk
and the main target that uses them is made by targ.mk.
The default Makefile makes the two makefiles.
The "-" special atom between the makefiles tells nmake to
finish gen.mk before starting targ.mk when
building with concurrency.
$ ls -l
total 0
-rw-r--r-- 1 richb richb 24 Jul 28 10:12 Makefile
-rw-r--r-- 1 richb richb 63 Jul 28 10:13 gen.mk
-rw-r--r-- 1 richb richb 52 Jul 28 10:13 targ.mk
$ cat Makefile
:MAKE: gen.mk - targ.mk
$ cat gen.mk
:ALL: genfiles
genfiles : .VIRTUAL
date > gen1.in
uname -a > gen2.in
$ cat targ.mk
:ALL: targ
targ : gen1.in gen2.in
cat $(*) > $(<)
$ nmake
gen.mk:
+ date
+ 1> gen1.in
+ uname -a
+ 1> gen2.in
targ.mk:
+ cat gen1.in gen2.in
+ 1> targ
Suggestions
We're 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!