We made some promises early in the paper that we haven't kept yet and now is a good time to deliver. The explanations depend on the .INIT, .ARGS, and .MAIN special atoms that we'll introduce in this section.
There's a target named .INIT that's automatically built right before anything else in your makefile. It can be convenient when you're debugging and is important if you want to do something, like execute a shell script, every time nmake process runs.
We've already seen an example where .INIT would help. Remember the disappearing print message that we blamed on the objectfile? If we go back to print.mk, make a target named .INIT, mark it with the .MAKE special atom, and move the print command into .INIT's action block
.INIT : .MAKE print this message comes from print hello : silent echo "hello, world"
then we get the message from print whenever we run nmake. The explanation is easy: the symbol tables written to the objectfile include our definition of .INIT, so the print command isn't lost because this time it's part of .INIT's action block.
nmake collects the targets from your command line, adds them to the prerequisite list of a special atom named .ARGS, and eventually goes back and builds everything it finds in .ARGS's prerequisite list. We'll need .ARGS to explain why we only get one message from,
nmake -f message.mk hello hello
but first we have to show you how to look at a prerequisite list.
There's an automatic variable named $(~) that stands for all the explicit prerequisites  of the current target. We happen to be interested in the prerequisites of .ARGS, so $(~) isn't quite what we want, but there's an easy way to use automatic variables to look at any target. Follow the character that identifies the automatic variable by the name of a target, and nmake gives you information about that target. For example, $(~.ARGS) is how we ask for the explicit prerequisites of .ARGS, so if we put
.INIT : .MAKE print .ARGS : $(~.ARGS) goodbye hello : silent echo "$(<), world"
in args.mk and type
nmake -f args.mk hello goodbye
.ARGS : hello goodbye hello, world goodbye, world
The first line is from the print statement that we put in .INIT's action block, and the two prerequisites are the targets we named on the command line.
Mention the same target twice on the command line and we know something unexpected happens when we use message.mk. Try it with args.mk
nmake -f args.mk hello hello
and the same thing happens,
.ARGS : hello hello, world
but now we can understand why. There's only one hello in .ARGS's prerequisite list and that's why we only get one message. But that's usually how prerequisite lists work: no matter how many times we say a target depends on a prerequisite, we'll only see it once when we look through the list.
nmake usually builds the first target in your makefile that doesn't look like a special atom  when there aren't any command line arguments, but there's a target named .MAIN that lets you pick your own defaults. For example, if we put
AUDIENCE = world .MAIN : hello goodbye hello : silent echo "$(<), $(AUDIENCE)"
in main.mk then all we have to do is type
nmake -f main.mk
when we want to say hello, because the prerequisites of .MAIN end up as the default targets.
You have to be careful where you put .MAIN. Move it to the end of main.mk and see what nmake builds when you don't tell it what to do. The explanation is easy, so we'll leave it to you. Hint: $(~.MAIN) and the technique we just used in args.mk will show you the prerequisites.