Highlights
Current Work
We are currently working on release lu3.6. Besides several enhancements and fixes release lu3.6 will have enhanced java support, including concurrent batched java compilations and built-in support for creating jar files. The jar rules from the newsletters will no longer be needed as the new rules include a number of enhancements over the old, newsletter rules. We are also working on a port to Windows® NT/2000. See the Windows NT/2000 article below for more information.
Support for Windows NT/2000
nmake release lu3.6 is being ported to Windows NT/2000. This will be the first time nmake is available for a Windows based platform. The Windows port is being done using AT&T's UWIN (UNIX for Windows) product. UWIN will be required, and must be obtained separately, to run this port. We are using UWIN from Wipro Technologies.
A Call for Beta Testers
We hope to start beta testing the win32 port in April. If you are interested in beta testing please contact us at nmake@alcatel-lucent.com. Since this is a very new platform for us we would like to get as much feedback as possible.
Other Platforms
We would like to know what other win32 based platforms you are interested in. If you have a need to run nmake on Cygwin, MKS Toolkit, or other UNIX environments for Windows please let us know at nmake@alcatel-lucent.com so can evaluate demand for these platforms.
Technical Notes
Jar Rules Update
The jar rules originally posted in issue 5
have had a minor update to deal with a problem reported in the field.
When the jarred class files are not inside a java package directory,
class files with a dollar sign ($) in their name are not
included in the jar file because the shell expands $name
as a shell variable when passing the filenames to the jar command.
Even though release lu3.6 will include jar support, an update for these rules are being provided for those who are not in a position to upgrade and still need the old rules. You can download the new jar rules and see Creating Jar Files for details on using the rules.
Here is an example of the problem. Notice a$xyz.class,
c$x.class, c$y.class, and c$z.class
are all missing in the generated jar file. Note that this only happens
when the class files are not contained in a java package directory.
$ cat Makefile
include jarrules.mk
JARROOT = classes
:ALL: abc.jar
abc.jar :JAR: classes
$ ls classes
a$xyz.class b.class c$y.class c.class
a.class c$x.class c$z.class
$ nmake
+ mkdir -p abc.tmpjar
+ cp classes/a$xyz.class abc.tmpjar/a$xyz.class
+ cp classes/a.class abc.tmpjar/a.class
+ cp classes/b.class abc.tmpjar/b.class
+ cp classes/c$x.class abc.tmpjar/c$x.class
+ cp classes/c$y.class abc.tmpjar/c$y.class
+ cp classes/c$z.class abc.tmpjar/c$z.class
+ cp classes/c.class abc.tmpjar/c.class
+ cd abc.tmpjar
+ jar cf ../abc.jar a.class a.class b.class c.class c.class c.class c.class
$ jar tvf abc.jar
403 Mon Apr 14 14:36:22 EDT 2003 META-INF/MANIFEST.MF
8 Mon Apr 14 14:36:20 EDT 2003 a.class
8 Mon Apr 14 14:36:20 EDT 2003 b.class
8 Mon Apr 14 14:36:20 EDT 2003 c.class
Here is the same example using the updated jar rules. The missing class files are now included.
$ nmake
+ mkdir -p abc.tmpjar
+ cp classes/a$xyz.class abc.tmpjar/a$xyz.class
+ cp classes/a.class abc.tmpjar/a.class
+ cp classes/b.class abc.tmpjar/b.class
+ cp classes/c$x.class abc.tmpjar/c$x.class
+ cp classes/c$y.class abc.tmpjar/c$y.class
+ cp classes/c$z.class abc.tmpjar/c$z.class
+ cp classes/c.class abc.tmpjar/c.class
+ cd abc.tmpjar
+ jar cf ../abc.jar a$xyz.class a.class b.class c$x.class c$y.class c$z.class c.class
$ jar tvf abc.jar
917 Mon Apr 14 14:42:08 EDT 2003 META-INF/MANIFEST.MF
12 Mon Apr 14 14:42:08 EDT 2003 a$xyz.class
8 Mon Apr 14 14:42:08 EDT 2003 a.class
8 Mon Apr 14 14:42:08 EDT 2003 b.class
10 Mon Apr 14 14:42:08 EDT 2003 c$x.class
10 Mon Apr 14 14:42:08 EDT 2003 c$y.class
10 Mon Apr 14 14:42:08 EDT 2003 c$z.class
8 Mon Apr 14 14:42:08 EDT 2003 c.class
Stray Lock Files
We have had a few reports of nmake's .ml lock files not
being removed after the build is finished. The behavior has been
unpredictable and thus not easy to reproduce or study. At this
point it appears to have only affected people using their own recurse
rules rather than the default :MAKE: operator. We have
had success in eliminating the problem by adding the special atoms
.LOCAL and .RECURSE.SEMAPHORE as prerequisites
to the definitions of the custom recurse rules. If you experience this
problem and it is not practical for you to convert to :MAKE:,
make sure your recurse rules are defined with these special atoms
and please contact us about your
status or to get more help.
lu3.5 -I flags
Many people have reported they get redundant -I flags
on the compile lines after upgrading to release lu3.5. This problem
occurs when the native compiler supports -I- (nmake
will use the native preprocessor instead of nmake cpp,) and the code
includes files using a directory prefix
(eg. #include "prefix/file.h").
In the following example you see one -Iinclude/stc for each
file in include/stc included by stc/hello.h:
$ cat Makefile
CC = /opt/exp/gnu/bin/gcc
.SOURCE.h : include
hello :: hello.c
$ cat hello.c
#include "stc/hello.h"
#include <stdio.h>
int main(){
printf("hello worlds\n");
return(0);
}
$ ls include/stc
a.h b.h c.h hello.h
$ nmake
+ /opt/exp/gnu/bin/gcc -O -Iinclude -Iinclude/stc -Iinclude/stc -Iinclud
e/stc -I- -c hello.c
+ /opt/exp/gnu/bin/gcc -O -o hello hello.o
This problem was introduced from an enhancement in lu3.5 to
support prefixinclude for
native compilers and will be fixed in lu3.6. In the mean time
the old behavior (pre-lu3.5) can be restored by setting
prefixinclude=0 in the makefiles or on the command line.
You may also need to add the prefix directory to .SOURCE.h
as shown below.
$ cat Makefile CC = /opt/exp/gnu/bin/gcc prefixinclude = 0 .SOURCE.h : include include/stc hello :: hello.c $ nmake + /opt/exp/gnu/bin/gcc -O -Iinclude -Iinclude/stc -I- -c hello.c + /opt/exp/gnu/bin/gcc -O -o hello hello.o
Tidbits
Exporting Variables to the Shell
Sometimes it is convenient to export nmake variables to the shell. There are three ways this can be accomplished.
MAKEEXPORT
The MAKEEXPORT feature was introduced in release lu3.3, but had a critical fix in lu3.4-p01. Using MAKEEXPORT is the easiest way to export nmake variables to the shell environment. MAKEEXPORT is a variable containing a colon separated list of variables to be exported to the shell. The specified variables will be exported in every shell action including both user defined rules and predefined nmake rules.
$ cat Makefile
ABC = abc
XYZ = xyz
MAKEEXPORT = ABC:XYZ
test.x : test.v
mytool $(*) > $(<)
$ nmake
+ ABC=abc
+ XYZ=xyz
+ export ABC XYZ
+ mytool test.v
+ 1> test.x
In the Action Block
Another method is to explicitly export a variable in the action block that needs the shell variable. This works well if the variable is needed only for some specific tool for which you have very few action blocks defined. If the variable is needed any many actions throughout the build this method becomes difficult to manage.
$ cat Makefile
ABC = abc
XYZ = xyz
test.x : test.v
export ABC=$(ABC)
export XYZ=$(XYZ)
mytool $(*) > $(<)
$ nmake
+ export ABC=abc
+ export XYZ=xyz
+ mytool test.v
+ 1> test.x
.ACTIONWRAP
The final solution is to use
.ACTIONWRAP,
which was introduced in release lu3.2.
.ACTIONWRAP allows you to wrap commands around all actions
that are sent to the shell. This includes both user defined rules and
predefined nmake rules. Note, if you are using the
output serialization feature
(ie. makelog) then you should avoid this method because
.ACTIONWRAP is already being used to support output
serialization.
$ cat Makefile
ABC = abc
XYZ = xyz
.ACTIONWRAP:
export ABC=$(ABC)
export XYZ=$(XYZ)
$(@)
test.x : test.v
mytool $(*) > $(<)
$ nmake
+ export ABC=abc
+ export XYZ=xyz
+ mytool test.v
+ 1> test.x
Tracing Rule Dependencies
Here is a technique for tracing through rule dependencies to find all generated class files, including secondary class files, given a list of java source files. It also illustrates two useful but currently undocumented nmake features. We plan to document these features in a future version of the reference and user manuals.
Assume we are processing a list of java files, and we need to obtain a
list of the associated class files. For example, we might want to
build a jar containing all of the class files. Due to a requirement
of the java language we know that the java compiler will always
generate x.class from a source file x.java.
However, the java compiler may generate additional class files since
each class goes into its own separate class file. For example, inner
classes and secondary, non-public top level classes will each go into
their own class file. Consequently simply transforming the .java suffix
into .class is not sufficient to produce all generated class files. For
the same reason, suffix-driven metarules are not sufficient by
themselves to properly manage java builds. .JOINT rules
provide one way to correctly specify this one-to-many dependency relationship:
a.class a1.class : a.java .JOINT
The standard :JAVA: assertion defined in JAVA.mk automatically
generates dependencies like these by scanning java source. Here is a
complete example showing :processjava:, a user-defined assertion
that needs to find the list of associated class files from a
list of java files specified on the right hand side.
$ cat Makefile ":processjava:" : .MAKE .OPERATOR print javafiles=$(>) print classfiles=$(<$(>:D:B:S=.class)) targ: silent print done a.class a1.class : a.java .JOINT b.class b1.class b2.class : b.java .JOINT c.class : c.java .JOINT d.class : d.java :processjava: a.java b.java c.java d.java $ nmake javafiles=a.java b.java c.java d.java classfiles=a.class a1.class b.class b1.class b2.class c.class d.class done
The first step is straightforward: $(>:D:B:S=.class)
transforms the list of java files into the same list with each suffix
changed to .class. This is guaranteed to find an associated class target
due to the java rule that the source filename must be constructed from the
class name. We then expand the single class target into the complete
list of jointly generated targets using the < automatic
variable applied to the known class target. This use of the <
variable to find all jointly generated targets for a non-active target is
not currently documented. Another undocumented usage illustrated here is the
application of an automatic variable to a token list rather than just
a single target.
Newsletter Feedback
We are always interested in feedback! Let us know what you think of the newsletter, how we may improve, or ideas you have for future issues. Send us a note at nmake@alcatel-lucent.com. All ideas, suggestions, and comments are welcome.