Nokia Networks Home

Nokia nmake Product Builder

Quick Links

Related Products

Tutorial: A Little Help With Nokia nmake

[Table of Contents] [Previous Section] [Next Section]

3. Extra Files

nmake does some things behind your back that you should know about. You won't need all the details, but a little knowledge is important. For example, realizing the .mo, .ms, and .ml suffixes have been claimed could prevent accidents; knowing something about the extra files nmake creates will help you understand important aspects of nmake's behavior.

3.1 The Objectfile

nmake builds an objectfile [8] from a makefile and uses its internal machinery to keep track of both files. If the objectfile is up to date nmake reads it instead of the makefile; otherwise nmake reads the makefile and builds a new objectfile that can be used next time. As far as nmake is concerned, the two files are supposed to be equivalent, but reading the objectfile saves time.

Objectfiles are associated with makefiles using a simple technique: nmake picks the name by removing the makefile's suffix, if there is one, and attaching .mo. For example, hello.mo is the objectfile associated with hello.mk. Even though there's some ambiguity [9] nmake isn't easily confused, because the name of the associated makefile is also recorded in the objectfile. If you're really curious, look at an objectfile with cat -v or od -c and see if you can find the name.

An objectfile is also sometimes called a "compiled makefile," but the terminology is a bit misleading. It suggests equivalence and implies you get exactly the same results no matter whether nmake reads the makefile or the objectfile. In reality there are differences - we'll give you an easy example.

3.1.1 A Small Surprise

We mentioned print earlier in the paper when we talked about the special words that sometimes need quoting. It's a simple command [10] that tells nmake to copy the rest of the line to standard output. If we put

     print this message comes from print

     hello :
        silent echo "hello, world"

in a file named print.mk and type

     nmake -f print.mk

we get:

     this message comes from print
     hello, world

No surprises yet, but run nmake again and the message from print disappears. It's easy to show this is due to the objectfile - remove print.mo or tell nmake to ignore the objectfile using the -o reread option

     nmake -f print.mk -o reread hello

and the message from print reappears.

The explanation is important, so pay attention. It may look like a mistake, but it's not because the objectfile isn't a translation of the makefile. Instead, most of what you'll find in an objectfile is a dump of several internal symbol tables in a portable format that nmake can digest quickly. nmake ends up with the same data in those symbol tables no matter which file (makefile or objectfile) it reads. But print doesn't create any data, so there's no record of it in the objectfile, and that's why the message disappeared.

By the way, there is an easy way to make sure print runs whenever nmake does, even if the objectfile is used. We'll show you how later in the paper when we talk about .INIT.

3.2 The Statefile

nmake needs a statefile to preserve information, like compiler flags, that may not be available the next time it runs, but nmake goes much farther and remembers lots of important information (e.g., file time stamps and when targets were built) in the statefile. nmake reads the statefile when it starts, updates it right before quitting, and builds targets when information it needs is missing from the statefile or conflicts with what's available from another source, like the file system.

Statefiles are associated with makefiles using the technique that we just described for objectfiles, except nmake attaches .ms instead of .mo as the identifying suffix. For example, hello.ms would be the statefile associated with hello.mk.

3.2.1 A State Variable

Put parentheses around a variable name, add it to a prerequisite list, and you've made the target depend on the variable. Here's a simple example that we'll save in a file named state.mk; it should help, as long as you close your eyes when you come to .VIRTUAL in the prerequisite list - we'll explain that one in a few sections:

     AUDIENCE = world

     goodbye : .VIRTUAL (AUDIENCE)
        silent echo "$(<), $(AUDIENCE)"

     hello : .VIRTUAL
        silent echo "$(<), $(AUDIENCE)"

We started with message.mk, split the assertion up, added .VIRTUAL to both prerequisite lists, and then turned AUDIENCE into a state variable by saying goodbye depends on (AUDIENCE). State variables are saved in the statefile and targets, like goodbye, that depend on a state variable are rebuilt when that variable changes.

It's easy to demonstrate the behavior, but first let's see what happens when we build hello, because it doesn't have AUDIENCE as a prerequisite. We get the usual message when we type,

     nmake -f state.mk hello

but try it again and nothing happens, and that's why we added .VIRTUAL to the prerequisite list. Change AUDIENCE on the command line and the silence continues. But try the same thing with goodbye and we get the expected message from

     nmake -f state.mk goodbye

and another one when we type:

     nmake -f state.mk AUDIENCE='New Jersey' goodbye

nmake rebuilds goodbye whenever we change AUDIENCE, and the state variable prerequisite is the reason why.

3.3 The Lockfile

There's one more special file, but this one is harder to find. nmake creates a lockfile [11] when it starts and removes it right before it quits, so we have to look for the lockfile while nmake is running. If we put

     lock :
        ls -l lock.ml

in a file named lock.mk and type

     nmake -f lock.mk lock

we get:

     + ls -l lock.ml
     ----------   1 drexler  sablime        0 Dec 28 15:06 lock.ml

That's the lockfile - it's empty, has no permissions, ends in .ml, and is associated with a makefile, just like the statefile and objectfile. The lockfile is there to protect the statefile from multiple updates, but it's not much of an obstacle. You get a message something like

    make: warning: another make has been running on lock.mk in . for the past 2.00s
    make: use -K to override

when nmake finds a lockfile that it didn't create. Follow nmake's advice and use the -K option or just remove the lockfile and nmake will run without complaining [12] but first be sure nmake really isn't using the makefile.

3.3.1 MAKEFILE

Our last example works because the makefile is named lock.mk, but renaming the makefile breaks the example. nmake remembers the name of your makefile [13] in a variable named MAKEFILE, so

     lock :
        ls -l `echo $(MAKEFILE) | sed 's/. [^.]*$//' | sed 's/$/.ml/'`

works no matter where we put the makefile. Incidentally, we used sed instead of basename, because nothing says we can't use a non-standard suffix, like .MK, in a makefile name. The sed stuff is ugly, so here's how you would do the same thing if you had more experience with nmake and knew about edit operators:

     lock :
        ls -l $(MAKEFILE:B:S=.ml)

We're not going to explain edit operators in this paper, but we think the example shows their advantage. Edit operators are efficient and often provide elegant solutions.

FOOTNOTES:

[8]
Existing documentation says object file, rather than objectfile.
[9]
For example, makefiles named hello.mk, hello.MK, and hello all map to the same objectfile.
[10]
The nmake programming language is described in chapter 5 of the nmake manual.
[11]
Existing documentation says lock file, rather than lockfile.
[12]
Telling nmake to skip the statefile update using the -o nowritestate option also works.
[13]
Actually just the first makefile from your command line.

[Table of Contents] [Previous Section] [Next Section]

Last Update: Friday,12-Aug-2016 12:19:17 EDT