A metarule is a transformation rule that describes how to build a file
with a name matching one pattern from a file matching another pattern.
For example the following metarule, defined in the base rules, makes a
.o object file from a corresponding
.c source file.
%.o : %.c (CC) (CCFLAGS) $(CC) $(CCFLAGS) -c $(>)
Metarules are chained as needed. Given the metarules
%.z : %.y
%.y : %.x and the source file
file.x, the target
file.z will be generated by first applying
%.y : %.x to build
file.y, and then applying
%.z : %.y to build
file.z. Chaining is not limited
to two metarules but may span several rules. Metarule closure is the process
of determining what all target file patterns can be generated from what
source file patterns by chaining rules together. Each metarule is closed
when the rule is parsed while the makefile is being compiled.
Project makefiles may define any number of local metarules. Under some rare conditions metarules may interact with each during the closure process resulting in a loop in the chain which may cause closure to take an excessive amount of time. Starting with nmake 13 a warning is issued if closure of a metarule exceeds 5 seconds.
One way to mitigate the problem is to compile the global rules file containing
the project metarules. By compiling the global rules the processing hit is
taken only once up front since closure takes place when the makefile is being
compiled. The local makefiles then load the compiled rules and skip the
closure processing. A global rules file is compiled using the nmake
-bcf flags as follows,
nmake -bcf global.mk
The above produces
global.mo which can be referenced as a
global makefile using the nmake
-g global.mo command line option.
Note, a compiled makefile cannot be referenced using the nmake
include statement in a makefile, the command line option
must be used. A project build script can be used to automatically keep the
global.mo updated when
global.mk changes before
starting a build since it won't be recompiled automatically.