Inference rules are templates that define how a file with one extension is created from a file with a different extension. When NMAKE encounters a description block that has no commands, it searches for an inference rule that matches the extensions of the target and dependent files. Similarly, if a dependent file doesn't exist, NMAKE looks for an inference rule that shows how to create the missing dependent from another file with the same base name.
Summary: Inference rules tell NMAKE how to create files with a specific extension.
Inference rules provide a convenient shorthand for common operations. For instance, you can use an inference rule to avoid repeating the same command in several description blocks. You can define your own inference rules or use predefined inference rules.
NOTE:
An inference rule is useful only when a target and dependent have the same base name, and have a one-to-one correspondence. For example, you cannot define an inference rule that replaces several modules in a library, because the modules would have different base names than the target library.
Inference rules can exist only for dependents with extensions that are listed in the .SUFFIXES directive. (For information on the .SUFFIXES directive, see Section 10.3.6, “Directives.”) NMAKE searches in the current or specified directory for a file whose base name matches the target and whose extension is listed in the .SUFFIXES list. If it finds such a file, it applies the inference rule that matches the extensions of the target and the located file.
The .SUFFIXES list specifies an order of priority for NMAKE to use when searching for files. If more than one file is found, and thus more than one rule matches a dependency line, NMAKE searches the .SUFFIXES list and uses the rule whose extension appears earlier in the list. For example, the dependency line
project.exe :
can be matched to several predefined inference rules and possibly one or more user-defined rules, all of which describe a command for creating an .EXE file. NMAKE uses the inference rule corresponding to the first matching file it finds.
An inference rule has the following syntax:
.fromext.toext:
commands
The first line lists two extensions: fromext extension represents the filename extension of a dependent file, and toext represents the extension of a target file. Extensions are not case sensitive.
The second line of the inference rule gives the command to create a target file of toext from a dependent file of fromext. Use the same rules for commands in inference rules as in description blocks. (See Section 10.3.1, “Description Blocks.”)
The inference-rule syntax described above tells NMAKE to look for the specified files in the current directory. You can also specify directories to be searched by NMAKE when it looks for files with the extensions fromext and toext. An inference rule that specifies paths has the following syntax:
{frompath}.fromext {topath}.toext:
commands
NMAKE searches in the frompath directory for files with the fromext extension. It uses commands to create files with the toext extension in the topath directory, if the fromext file has a later modification time than the toext file.
The paths in the inference rule must exactly match the paths explicitly specified in the dependency line of a description block.
If you use a path on one element of the inference rule, you must use paths on both. You can specify the current directory for either element by using the operating system notation for the current directory, which is a dot (.), or by specifying an empty pair of braces.
You can specify only one path for each element in an inference rule. To specify more than one path, repeat the inference rule with the alternate path.
You can define inference rules in the description file or in TOOLS.INI (see Section 10.6, “The TOOLS.INI File”). An inference rule lists two file extensions and one or more commands.
Example 1
The following inference rule tells NMAKE how to build a .OBJ file from a .C file:
.c.obj:
CL /c $<
In this example, the predefined macro $< represents the name of a dependent that has a more recent modification time than the target.
NMAKE applies this inference rule to the following description block:
sample.obj :
The description block lists only a target, SAMPLE.OBJ. Both the dependent and the command are missing. However, given the target's base name and extension, plus the inference rule, NMAKE has enough information to build the target.
NMAKE first looks for a file with the same base name as the target and with one of the extensions in the .SUFFIXES list. If SAMPLE.C exists (and no files with higher-priority extensions exist), NMAKE compares its time to that of SAMPLE.OBJ. If SAMPLE.C has changed more recently, NMAKE compiles it using the CL command listed in the inference rule:
CL /c sample.c
Example 2
The following inference rule compares a .C file in the current directory with the corresponding .OBJ file in another directory:
{.}.c{c:\objects}.obj:
cl /c $<;
The path for the .C file is represented by a dot. A path for the dependent extension is required because one is specified for the target extension.
This inference rule matches a dependency line containing the same combination of paths, such as:
c:\objects\test.obj : test.c
This rule does not match a dependency line such as:
test.obj : test.c
In this case, NMAKE uses the predefined inference rule .c.obj when building the target.
NMAKE provides predefined inference rules containing commands for creating object, executable, and resource files. Table 10.6 describes the predefined inference rules.
Table 10.6 Predefined Inference Rules
Rule | Command | Default Action |
.asm.obj | $(AS) $(AFLAGS) /c $*.asm | ML /c $*.ASM |
.asm.exe | $(AS) $(AFLAGS) $*.asm | ML $*.ASM |
.bas.obj | $(BC) $(BFLAGS) $*.bas; | BC $*.BAS; |
.c.obj | $(CC) $(CFLAGS) /c $*.c | CL /c $*.C |
.c.exe | $(CC) $(CFLAGS) $*.c | CL $*.C |
.cbl.obj | $(COBOL) $(COBFLAGS) $*.cbl; | COBOL $*.CBL; |
.cbl.exe | $(COBOL) $(COBFLAGS) $*.cbl, $*.exe; | COBOL $*.CBL, $*.EXE; |
.for.obj | $(FOR) /c $(FFLAGS) $*.for | FL /c $*.FOR |
.for.exe | $(FOR) $(FFLAGS) $*.for | FL $*.FOR |
.pas.obj | $(PASCAL) /c $(PFLAGS) $*.pas | PL /c $*.PAS |
.pas.exe | $(PASCAL) $(PFLAGS) $*.pas | PL $*.PAS |
.rc.res | $(RC) $(RFLAGS) /r $* | RC /r $* |
For example, assume you have the following description file:
sample.exe :
This description block lists a target without any dependents or commands. NMAKE looks at the target's extension (.EXE) and searches for an inference rule that describes how to create an .EXE file. Table 10.6 shows that more than one inference rule exists for building an .EXE file. NMAKE looks for a file in the current or specified directory that has the same base name as the target sample and one of the extensions in the .SUFFIXES list. For example, if a file called SAMPLE.FOR exists, NMAKE applies the .for.exe inference rule. If more than one file with the base name SAMPLE is found, NMAKE applies the inference rule for the extension listed earliest in the .SUFFIXES list. In this example, if both SAMPLE.C and SAMPLE.FOR exist, NMAKE uses the .c.exe inference rule to compile SAMPLE.C and links the resulting file SAMPLE.OBJ to create SAMPLE.EXE.
NOTE:
By default, the options macros such as CFLAGS shown in Table 10.5 are undefined. As explained in Section 10.3.4.2, “Using Macros,” this causes no problem; NMAKE replaces an undefined macro with a null string. Because the predefined options macros are included in the inference rules, you can define these macros and have their assigned values passed automatically to the predefined inference rules. The predefined inference rules are listed in Table 10.6.
If the same inference rule is defined in more than one place, NMAKE uses the rule with the highest precedence. The precedence from highest to lowest is
1.An inference rule defined in the description file. If more than one, the last one applies.
2.An inference rule defined in the TOOLS.INI file. If more than one, the last one applies.
3.A predefined inference rule.
User-defined inference rules always override predefined inference rules. NMAKE uses a predefined inference rule only if no user-defined inference rule exists for a given target and dependent.
If two inference rules could produce a target with the same extension, NMAKE uses the inference rule whose dependent's extension appears first in the .SUFFIXES list. See Table 10.7 in the next section, “Directives.”