18.10 Sequence of NMAKE Operations

When you write a complex makefile, it can be helpful to know the sequence in which NMAKE performs operations. This section describes those operations and their order.

Summary: NMAKE first looks for a makefile.

When you run NMAKE from the command line, NMAKE's first task is to find the makefile:

1.If the /F option is used, NMAKE searches for the filename specified in the option. If NMAKE cannot find that file, it returns an error.

2.If the /F option is not used, NMAKE looks for a file named MAKEFILE in the current directory. If there are targets on the command line, NMAKE builds them according to the instructions in MAKEFILE. If there are no targets on the command line, NMAKE builds only the first target it finds in MAKEFILE.

3.If NMAKE cannot find MAKEFILE, NMAKE looks for target files on the command line and attempts to build them using inference rules (either defined by the user in TOOLS.INI or predefined by NMAKE). If no target is specified, NMAKE returns an error.

Summary: Macro definitions follow a priority.

NMAKE then assigns macro definitions with the following precedence (highest to lowest):

1.Macros defined on the command line

2.Macros defined in a makefile or include file

3.Inherited macros

4.Macros defined in the TOOLS.INI file

5.Predefined macros (such as CC and RFLAGS)

Macro definitions are assigned first in order of priority and then in the order in which NMAKE encounters them. For example, a macro defined in an include file overrides a macro with the same name from the TOOLS.INI file. Note that a macro within a makefile can be redefined; a macro is valid from the point it is defined until it is redefined or undefined.

Summary: Inference rules also follow a priority.

NMAKE also assigns inference rules, using the following precedence (highest to lowest):

1.Inference rules defined in a makefile or include file

2.Inference rules defined in the TOOLS.INI file

3.Predefined inference rules (such as .c.obj)

You can use command-line options to change some of these priorities.

The /E option allows macros inherited from the environment to override macros defined in the makefile.

The /R option tells NMAKE to ignore macros and inference rules that are defined in TOOLS.INI or are predefined.

Summary: NMAKE preprocesses directives before running the makefile commands.

Next, NMAKE evaluates any preprocessing directives. If an expression for conditional preprocessing contains a program in brackets ([]), the program is invoked during preprocessing and the program's exit code is used in the expression. If an !INCLUDE directive is specified for a file, NMAKE preprocesses the included file before continuing to preprocess the rest of the makefile. Preprocessing determines the final makefile that NMAKE reads.

Summary: NMAKE updates targets in the makefile.

NMAKE is now ready to update the targets. If you specified targets on the command line, NMAKE updates only those targets. If you did not specify targets on the command line, NMAKE updates only the first target in the makefile. If you specify a pseudotarget, NMAKE always updates the target. If you use the /A option, NMAKE always updates the target, even if the file is not out-of-date.

NMAKE updates a target by comparing its time stamp to the time stamp of each dependent of that target. A target is out-of-date if any dependent has a later time stamp; if the /B option is specified, a target is out-of-date if any dependent has a later or equal time stamp.

If the dependents of the targets are themselves out-of-date or do not exist, NMAKE updates them first. If the target has no explicit dependent, NMAKE looks for an inference rule that matches the target. If a rule exists, NMAKE updates the target using the commands given with the inference rule. If more than one rule applies to the target, NMAKE uses the priority in the .SUFFIXES list to determine which inference rule to use.

Summary: Errors usually stop the build.

NMAKE normally stops processing the makefile when a command returns a nonzero exit code. In addition, if NMAKE cannot tell whether the target was built successfully, it deletes the target. The /I command-line option, .IGNORE directive, !CMDSWITCHES directive, and dash () command modifier all tell NMAKE to ignore error codes and attempt to continue processing. The /K option tells NMAKE to continue processing unrelated parts of the build if an error occurs. The .PRECIOUS directive prevents NMAKE from deleting a partially created target if you interrupt the build with CTRL+C or CTRL+BREAK. You can document errors by using the !ERROR directive to print descriptive text. The directive causes NMAKE to print some text, then stop the build.