Nokia nmake Product Builder
Customer Support Newsletter

http://www.bell-labs.com/project/nmake/newsletters/

Issue No. 13 - December 2002
Highlights
  1. Release lu3.5 patch 01
  2. JavaDeps lu2.0.3
Technical Notes
  1. Solaris 2.9 Verified
  2. A Transition to :JAVA:
Tidbits
  1. State Variables for Define Flags
  2. Newsletter Feedback
Contacts
email: nmake@alcatel-lucent.com (tech support)
email: software@alcatel-lucent.com (licenses/orders)
web: http://www.bell-labs.com/project/nmake/


Highlights

Patch 01 for lu3.5

Patch level 01 for lu3.5 is now available for download. The patch overlays lu3.5. Installation is automated and includes an option to back-out the patch and restore your nmake installation to its previous state. For details see the lu3.5-p01 patch page.

The following files are affected:

Here is a summary of the lu3.5-p01 fixes:

index

JavaDeps lu2.0.3

A JavaDeps update release, JavaDeps-lu2.0.3, coincides with the lu3.5-p01 patch release. JavaDeps is an optional package and only required for projects building Java code using the nmake supplied :JAVA: operator. Although the JavaDeps update does not require the lu3.5 patch, there are several java related fixes in the lu3.5 patch so we recommend upgrading both for projects currently using nmake with JavaDeps. For details see the JavaDeps page and the lu3.5-p01 patch page.

JavaDeps lu2.0.3 includes the following fixes:

index


Technical Notes

Solaris 2.9 Verified

We have recently verified nmake lu3.4 and lu3.5 on Solaris 2.9 and found no major problems. It is safe to run nmake on Solaris 2.9. However, you should be aware that the system sorting routines in 2.9 are sensitive to the locale for category LC_COLLATE. Since nmake uses the system sorting routines the :H and :L edit operators may produce unexpected sort results. Exporting LC_COLLATE=C in the shell environment will give you the traditional UNIX sort behavior.

Notice the sort order on Solaris 2.6:

$ uname -sr
SunOS 5.6

$ sort list
a.h
aa.h
b.h
bb.h

Now notice Solaris 2.9 gives different result until LC_COLLATE is set:

$ uname -sr
SunOS 5.9

$ sort list
aa.h
a.h
bb.h
b.h

$ export LC_COLLATE=C

$ sort list
a.h
aa.h
b.h
bb.h

If you are using Solaris 2.9 and you have nmake rules sensitive to sort order we recommend you set export LC_COLLATE=C in your build environment for consistency across platforms. We plan to address this in the next release so sort results from nmake are consistent by default.

Update 12/04/2002: Gary Sitzmann wrote in to tell us the defaults can be changed system wide, for all users, by setting the LC_ variables to C in file /etc/default/init on Solaris 2.8 and 2.9. Thanks Gary!.

index

A Transition to :JAVA:

The nmake team recently transitioned our JavaDeps build to use the standard :JAVA: operator. Since we started working with the JavaDeps code before our java support was implemented we initially used some interim nmake rules for building the java code. Here we will take a look at our before and after results of the transition.

The original makefile was about 48 lines without comments and white-space. By design it rebuilt all the java code when anything changed since dependencies were not being tracked. It also generated the jdeps.jar file and the source and binary distribution tar files. The generation of the jar and tar files required all the class and distribution files to be in the same node, so building incrementally in the viewpath did not work too well. The original makefile can be seen below.

/*
 * Original Makefile for JavaDeps package
 */

PACKAGE := JavaDeps
VERSION := lu2.0.3
distDir := $(PACKAGE)-$(VERSION)

clobber = 1

/*
 * Directory variables
 */

INSTALLROOT = $(VROOT)/prod
SRCDIR := $(INSTALLROOT)/src
CLASSDIR := $(INSTALLROOT)/bin
DOCDIR := $(INSTALLROOT)/doc

/*
 * Tools variables
 */

JAVAC = javac
JAVACFLAGS = -d $(CLASSDIR)
JAR = jar

/*
 * Source files variables
 */

grammarFile := Java1.2.jj
grammarSrcs := Java.java JavaConstants.java JavaTokenManager.java \
	      ASCII_UCodeESC_CharStream.java ParseException.java \
	      Token.java TokenMgrError.java

jdepsSrcs := DepTable.java ParseOptions.java InvalidOptionException.java \
	    JavaDeps.java ParameterEnumeration.java JarZipTable.java \
	    SyntaxDecoration.java

jfiles := $(grammarSrcs) $(jdepsSrcs)

distSrcs := $(grammarFile) $(jfiles) 
distDocs := native.html usage.html welcome.html win95.html grammar-mods
distMisc := jdeps Makefile README.jdeps synconfig ChangeLog \
	    BUGS COPYING MANIFEST.MF INSTALL
distFiles := jdeps.jar README.jdeps synconfig COPYING jdeps INSTALL

TARSRC = $(INSTALLROOT)/$(distDir)-src.tar
TARBIN = $(INSTALLROOT)/$(distDir).tar

.SOURCE : $(VROOT)/src/java $(VROOT)/src/doc

:ALL: $(INSTALLROOT)/jdeps.jar - .INSTALL - $(TARSRC) $(TARBIN)

/*
 * Make jdeps.jar
 */

$(INSTALLROOT)/jdeps.jar : MANIFEST.MF .javafiles
	cd $(CLASSDIR)
	date
	$(JAR) cmf $(*:N=*.MF:P=A) $(<:D=..:B:S) smr
	ls -l $(<:D=..:B:S)

.javafiles : $(jfiles) .JOINT .VIRTUAL
	$(JAVAC) $(JAVACFLAGS) $(*)

$(DOCDIR) :INSTALLDIR: $(distDocs)
$(SRCDIR) :INSTALLDIR: $(distSrcs)
$(INSTALLROOT) :INSTALLDIR: $(distMisc:N!=jdeps)
$(INSTALLROOT) :INSTALLDIR: jdeps mode=555

/*
** the tar files cannot be generated through the viewpath.
** a full build needs to be in the current node.
*/
$(TARSRC) $(TARBIN) :JOINT: $(distSrcs) $(distDocs) $(distMisc)
	rm -f $(<)
	cd $(INSTALLROOT)
	tar chf $(<:O=1:D=..:B:S) .
	tar chf $(<:O=2:D=..:B:S) $(distFiles)
	mv $(<:D=..:B:S) .

/*
 * clobber previously built targets
 */

.CLOBBER : .CLEAR .CLEARARGS .ONOBJECT .NOSTATEFILE
	$("$(.CLOBBER.:T=F:P=L=0) $(.BUILT.:A=.REGULAR:P=L=0)":Q:K=$(IGNORE) $(R
M) $(RMFLAGS))
	$(IGNORE) $(RM) -rf $(CLASSDIR)/smr

To use :JAVA: we split the makefile into four pieces. That sounds like a lot, but the result is still much smaller and easier to maintain. Since nmake does not yet include jar support we used the jar rules published in newsletter issue 5 to build both the jar and the tar files, which recommends the jar creation to be in a separate makefile from the java build due to nmake's directory caching. So we have one makefile to build the class files, one for the jar file and one for the tar file. The main makefile sets some variables and calls the other three makefiles in sequence using the :MAKE: operator. Below are the new files.

Makefile:

PACKAGE := JavaDeps
VERSION := lu2.1
PKGNAME := $(PACKAGE)-$(VERSION)

.EXPORT : PACKAGE VERSION PKGNAME

:MAKE: java.mk - jar.mk - tar.mk

java.mk:

/*
** This is not a typical JAVAPACKAGEROOT setting.
** It should allow building in the official environment (which uses VROOT/src)
** or from the JavaDeps source distribution package (use VPATH=$PWD).
*/ 
JAVAPACKAGEROOT = $(VROOT:L:N=java:Y?$(VROOT)?$(VROOT)/src?)
JAVACLASSDEST = classes

.INSTALL : .MAIN

:JAVA: java

jar.mk:

include "jarrules.mk"

:ALL: jdeps.jar

jdeps.jar :JAR: classes JARROOT=classes

tar.mk:

include "jarrules.mk"
JAR = tar

clobber = 1

distBIN = jdeps jdeps.jar synconfig README.jdeps COPYING INSTALL
distSRC = doc java ChangeLog BUGS MANIFEST.MF           \
	  Makefile java.mk jar.mk tar.mk jarrules.mk localjavadeps

JARTYPES=*

$(VROOT)/prod :INSTALLDIR: $(PKGNAME).tar $(PKGNAME)-src.tar

:ALL: jdeps - $(PKGNAME).tar $(PKGNAME)-src.tar

$(PKGNAME).tar :JAR: $(distBIN)
$(PKGNAME)-src.tar :JAR: $(distSRC) $(distBIN)

Even though we now have four makefiles we have a total of only 23 lines (not counting comments and white-space), which is just under half the size of the original. And as you can see the resulting files are much easier to read. We have realized the following benefits from the transition:

index


Tidbits

State Variables for Define Flags

State variables are variables whose values are stored in the state files. By storing the values nmake can detect when they change and trigger associated actions. One use of state variables is to generate -D define flags for the compiler. Unfortunately, many users do not take advantage of this feature.

Instead of hard-coding -D flags in CCFLAGS, state variables can be defined in the makefile. When nmake scans code for include files it also detects implicit variables and will generate corresponding -D flags for the code that use the variables. Using state variables has a couple advantages over hard-coding the -D flags.

  1. Changing the value of a state variable will recompile only the affected code, where changing CCFLAGS will recompile everything.
  2. The -D flags are generated only for compilations that need them. The build output will show which code actually uses which defines.

Let's take a look at an example.

$ cat Makefile 
CC = /opt/exp/gnu/bin/gcc
MAX == 100
test :: main.c init.c

$ cat main.c
int main() {
    init();
    return(0);
}

$ cat init.c
#include <stdio.h>
int init() {
    printf("MAX is %d\n",MAX);
}

$ nmake
+ /opt/exp/gnu/bin/gcc -O -I- -c main.c
+ /opt/exp/gnu/bin/gcc -O -I- -DMAX=100 -c init.c
+ /opt/exp/gnu/bin/gcc -O -o test main.o init.o

$ ./test
MAX is 100

Here you can see nmake added -DMAX=100 only for init.c since main.c does not use MAX.

What happens if we change MAX?

$ cat Makefile
CC = /opt/exp/gnu/bin/gcc
MAX == 200
test :: main.c init.c

$ nmake
+ /opt/exp/gnu/bin/gcc -O -I- -DMAX=200 -c init.c
+ /opt/exp/gnu/bin/gcc -O -o test main.o init.o

$ ./test
MAX is 200

Notice only init.c was recompiled and it now uses the new value of MAX.

We can also use state variables for #ifdef directives.

$ cat init.c
#include <stdio.h>
int init() {
#ifdef DEBUG
    printf("debug: entering init()\n");
#endif
    printf("MAX is %d\n",MAX);
}

$ nmake DEBUG==1
+ /opt/exp/gnu/bin/gcc -O -I- -DMAX=200 -DDEBUG -c init.c
+ /opt/exp/gnu/bin/gcc -O -o test main.o init.o

$ ./test
debug: entering init()
MAX is 200

This time the state variable is defined on the nmake command line. This works the same as setting it in the makefile, but is handy for making temporary changes.

And of course, if we rebuild without setting DEBUG then init.c will be recompiled without the define set.

$ nmake
+ /opt/exp/gnu/bin/gcc -O -I- -DMAX=200 -c init.c
+ /opt/exp/gnu/bin/gcc -O -o test main.o init.o

$ ./test
MAX is 200

If you are still hard-coding your -D define flags then you should try out state variables.

index


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.

index

<<home / newsletters