Order-only targets as in GNU Make - for Microsoft NMAKE? - makefile

GNU Make allows to specify order-only targets:
Occasionally [...] you have a situation where you want to impose a specific ordering on the rules to be invoked without forcing the target to be updated if one of those rules is executed. In that case, you want to define order-only prerequisites. Order-only prerequisites can be specified by placing a pipe symbol (|) in the prerequisites list: any prerequisites to the left of the pipe symbol are normal; any prerequisites to the right are order-only:
targets : normal-prerequisites | order-only-prerequisites
Order-only prerequisites are not contained in $^; you may refer to them using $|.
I find this useful for specifying system libraries as additional dependencies for linking.
CXX = cl
CXXFLAGS = /nologo /W4 /EHsc /MD
RC = rc
RCFLAGS = /nologo
# Link executables; $^ = all prerequisites; $| = order-only prerequisites
%.exe: %.obj %.res
$(CXX) $(CXXFLAGS) /Fe$# $^ $|
# Compile source files
%.obj: %.cpp
$(CXX) $(CXXFLAGS) /c /Fo$# $^
# Compile resource files
%.res: %.rc
$(RC) $(RCFLAGS) /r /fo$# $^
# System libraries needed for linking. Specify them as order-only prerequisites
# so their (no-op) rule being executed (due to their absence from the build
# directory) won't make the target appear out of date.
ErrorShow.exe: | user32.lib
Singleton.exe: | user32.lib advapi32.lib
ProcessInfo.exe: | user32.lib advapi32.lib gdi32.lib
# Set libraries as no-op targets to satisfy rule existence requirement.
advapi32.lib:
gdi32.lib:
user32.lib:
Is there any way to have Microsoft NMAKE do the equivalent?

Unfortunately no, Microsoft NMAKE does not have anything like GNU make's order-only prerequisites, and given that they've long-since moved on to other build tools like MSBuild it's not likely that Microsoft will ever add such a feature.
However, ElectricAccelerator, a high-performance GNU make and NMAKE replacement from Electric Cloud, does support order-only prerequisites in NMAKE mode. You might give that a try.
(Disclaimer: I'm the architect and lead developer of ElectricAccelerator)

Related

GNU Make: Force use of my own version of a rule

I have this rule in my Makefile:
%: ${OBJ}/%.o ${OBJ}/AgentProgram.o ${LIB}
$(CXX) $^ ${LDFLAGS} ${LIB_DIRS} ${LIBS} $(OUTPUT_OPTION)
If obj/Foo.o exists, make will use this rule. However, if the object doesn't already exist, it will use the built-in rule and attempt to directly compile from my .cpp.
Is there some way to define this rule as the default, or turn off the built-in rule?
My workaround is to modify my make bins target to produce all .o files first. It wasn't that hard in this case, I altered:
bins: ${BINS}
and turned it into this: (I already had ${OBJECTS} available)
bins: ${OBJECTS} ${BINS}
You can cancel pattern rules, including built-in pattern rules, by defining them without a recipe:
%: %.c
%: %.cpp
will remove the pattern rule for creating binaries from a .c and a .cpp.
Or, with a sufficiently new version of GNU make, you can disable ALL builtin rules by adding this to your makefile:
MAKEFLAGS += -r
(see the manual for the meaning of the -r option).

Forcing the order of implicit rule/pattern rule evaluation in GNU Make

I have a domain specific language compiler (homemade) which takes a file x.inflow and generates two files: x.c and x.h. The C file is compiled in the conventional manner and the generated header file has to be included into any file that calls the functions defined within it.
The header files therefore have to be generated before any C files that use them are compiled. My current Makefile, below, works fine except for the first build from clean where it can try and compile main.c before the header file that it includes has been created.
NAME = simplest
OBJ = $(patsubst %.c,%.o,$(wildcard *.c)) \
$(patsubst %.inflow,%.o,$(wildcard *.inflow))
CC = gcc
CFLAGS = -g -Wall
$(NAME): $(OBJ)
$(CC) $(CFLAGS) -o $# $^ $(CLIBS)
# Dependencies for existing .o files.
-include $(OBJ:.o=.d)
# Compile an inflow file into both a .c and .h file.
# Note that this rule has two targets.
%.c %.h: %.inflow
inflow $<
# Compile object files and generate dependency information.
%.o: %.c
$(CC) -MD -MP -c $(CFLAGS) -o $# $<
Obviously, I can fix this for specific cases by adding, for example (where simplest.h is a generated header):
main.o: simplest.h
But is there a general way to force one type of pattern rule (%.c %.h: %.inflow) to be run before any invokations of another (%.o: %.c)?
Well, you can force any target to be run before any other target with order-only prerequisites. So for example, you can write:
%.o : %.c | simplest.h
$(CC) -MD -MP -c $(CFLAGS) -o $# $<
which will ensure that no target that uses this pattern rule to build will be invoked before the target simplest.h is created. However, I don't think you can put patterns in an order-only prerequisite. To be honest, I've never tried it so it's possible that it works, I'm not sure.
If not, you could just list all the order-only prerequisites in the %.o pattern rule; this would ensure that all the inflow files are generated before any of the object files are built. That's probably OK.
It seems the problem is twofold:
Make doesn't know that it needs to generate simplest.h before compiling main.c.
You don't want to have to explicitly tell Make about the dependency (and remember to update it when it changes).
Rather than force Make to evaluate rules in a set order, you can solve your problem by letting Make create the dependencies for you. Check out this section of the Gnu Make manual: http://www.gnu.org/software/make/manual/make.html#Automatic-Prerequisites
When you run Make, it will scan your source files and gather their dependencies for you (and you won't have to explicitly list that main.o depends on simplest.h).

Makefile implicit rules matching .c OR .cpp

I'm trying to add an implicit rule to a Makefile, and I'd like it to handle compilation of .c and .cpp files the same way. The rule I have for .c files is as follows:
%.obj: %.c
cl /c $(CFLAGS) $<
What I'd like, though, is for the right side of the pattern to match .c OR .cpp, depending on which file is available. Is this possible? I've perused the Make manual, but haven't found what I'm looking for. Any help would be greatly appreciated.
Just use two rules which is equivalent to "or" in the make language:
%.obj: %.c
cl /c $(CFLAGS) $<
%.obj: %.cpp
cl /c $(CFLAGS) $<
At the end these are two different source languages and you may well end up desiring different flags.

Working with multiple source file extensions in a makefile

I have a c++ project with various extensions for the source files (.cpp, .c, .cc) and various extensions for the header files (.hpp, .h, .hh). The source files are located in a directory called SRC, and the header files are predictably in a directory called INC.
I would like to compile the source with a rule like
vpath %.c $(SRC)
%.o: %.c
$(COMPILER) $(FLAGS) $< $(INCFLAG)$(INC)
This of course works if I know the source file will be of the form %.c, but in the case of multiple possible file extensions, I would need to build a similar rule for %.cpp and %.cc as well. Of course three rules isn't a big deal to write, but it would be nice to be able to use this makefile as a drag and drop for any project, even in a different language, without having to re-write the rules.
So how can I write a rule (or some other construct that accomplishes the same goal) that works like:
SRC_EXT = cpp c cc
vpath %.$(SRC_EXT) $(SRC)
%.o: %.$(SRC_EXT)
$(COMPILER) $(FLAGS) $< $(INCFLAG)$(INC)
Thanks for your help.
You can't in standard POSIX make. However since you mention vpath I'll assume you're using GNU make. If you have a sufficiently new version (3.81 or newer), you can do this easily enough with call and eval:
SRC_EXT = cpp c cc
define compile_rule
%.o : %.$1
$$(COMPILER) $$(FLAGS) $$< $$(INCFLAG)$$(INC)
endef
$(foreach EXT,$(SRC_EXT),$(eval $(call compile_rule,$(EXT))))
If you don't have sufficiently new GNU make, or would prefer an alternate solution, you can do the same thing with generated makefiles.

What are double-colon rules in a Makefile for?

Section 4.13 of the GNU Make manual describes the so-called double-colon rules:
Double-colon rules are rules written with ‘::’ instead of ‘:’ after the target names. They are handled differently from ordinary rules when the same target appears in more than one rule.
When a target appears in multiple rules, all the rules must be the same type: all ordinary, or all double-colon. If they are double-colon, each of them is independent of the others. Each double-colon rule's commands are executed if the target is older than any prerequisites of that rule. If there are no prerequisites for that rule, its commands are always executed (even if the target already exists). This can result in executing none, any, or all of the double-colon rules.
Double-colon rules with the same target are in fact completely separate from one another. Each double-colon rule is processed individually, just as rules with different targets are processed.
The double-colon rules for a target are executed in the order they appear in the makefile. However, the cases where double-colon rules really make sense are those where the order of executing the commands would not matter.
Double-colon rules are somewhat obscure and not often very useful; they provide a mechanism for cases in which the method used to update a target differs depending on which prerequisite files caused the update, and such cases are rare.
Each double-colon rule should specify commands; if it does not, an implicit rule will be used if one applies. See section Using Implicit Rules.
I kinda grok the meaning of each sentence of this section individually, but it's still not clear to me what double-colon rules are for. As for being rare, I have not yet seen any open-source project whose Makefile did not begin with
all::
Therefore: What's the intended purpose of double-colon rules in Makefiles?
Each :: rule is processed independently, so it can be simpler. For example, the single rule:
libxxx.a : sub1.o sub2.o
ar rv libxxx.a sub1.o
ar rv libxxx.a sub2.o
can be replaced with two simpler rules:
libxxx.a :: sub1.o
ar rv libxxx.a sub1.o
libxxx.a :: sub2.o
ar rv libxxx.a sub2.o
Utilities like AutoMake have an easier time spitting out many simple rules than a few complex ones.
A great answer with more examples was posted, then taken down, then found here:
https://web.archive.org/web/20180122002430/http://owen.sj.ca.us/~rk/howto/slides/make/slides/makecolon.html
Thanks to R.K. Owen for writing it, and Edward Minnix for finding it again!
There are 3 situations where the double colon are useful:
Alternate between the compile rules based on which prerequisite is newer than the target. The following example is based on "Example 19-3. Double-colon rules" from http://books.gigatux.nl/mirror/cinanutshell/0596006977/cinanut-CHP-19-SECT-3.html
Sample .c file:
c#desk:~/test/circle$ cat circle.c
#include <stdio.h>
int main (void)
{
printf("Example.\n");
return 0;
}
Makefile used:
c#desk:~/test/circle$ cat Makefile
# A makefile for "circle" to demonstrate double-colon rules.
CC = gcc
RM = rm -f
CFLAGS = -Wall -std=c99
DBGFLAGS = -ggdb -pg
DEBUGFILE = ./debug
SRC = circle.c
circle :: $(SRC)
$(CC) $(CFLAGS) -o $# -lm $^
circle :: $(DEBUGFILE)
$(CC) $(CFLAGS) $(DBGFLAGS) -o $# -lm $(SRC)
.PHONY : clean
clean :
$(RM) circle
Outcome:
c#desk:~/test/circle$ make circle
gcc -Wall -std=c99 -o circle -lm circle.c
make: *** No rule to make target 'debug', needed by 'circle'. Stop.
c#desk:~/test/circle$ make circle
gcc -Wall -std=c99 -o circle -lm circle.c
gcc -Wall -std=c99 -ggdb -pg -o circle -lm circle.c
c#desk:~/test/circle$ vim circle.c
c#desk:~/test/circle$ make circle
gcc -Wall -std=c99 -o circle -lm circle.c
c#desk:~/test/circle$ vim debug
c#desk:~/test/circle$ make circle
gcc -Wall -std=c99 -ggdb -pg -o circle -lm circle.c
Make a pattern rule terminal.
The following example explains this situation: the a.config file is obtained from a.cfg, which in turn is obtained from a.cfg1 (a.cfg being the intermediate file).
c#desk:~/test/circle1$ ls
a.cfg1 log.txt Makefile
c#desk:~/test/circle1$ cat Makefile
CP=/bin/cp
%.config:: %.cfg
#echo "$# from $<"
#$(CP) $< $#
%.cfg: %.cfg1
#echo "$# from $<"
#$(CP) $< $#
clean:
-$(RM) *.config
Outcome (as the %.config rule is terminal, make inhibits the creation of the intermediate a.cfg file from a.cfg1):
c#desk:~/test/circle1$ make a.conf
make: *** No rule to make target 'a.conf'. Stop.
Without the double colon for the %.config, the outcome is:
c#desk:~/test/circle1$ make a.config
a.cfg from a.cfg1
a.config from a.cfg
rm a.cfg
Make a rule that executes always (useful for clean rules). The rule must not have prerequisites!
c#desk:~/test/circle3$ cat Makefile
CP=/bin/cp
a.config::
#echo "Always" >> $#
a.config::
#echo "Always!" >> $#
clean:
-$(RM) *.config
Outcome:
c#desk:~/test/circle3$ make a.config
c#desk:~/test/circle3$ cat a.config
Always
Always!
c#desk:~/test/circle3$ make a.config
c#desk:~/test/circle3$ cat a.config
Always
Always!
Always
Always!
They are handy for non-recursive makefiles and targets like clean. That is, an individual .mk file can add its own commands to the clean target already defined elsewhere.
Documentation gives an answer:
Double-colon rules are somewhat obscure and not often very useful; they provide a mechanism for cases in which the method used to update a target differs depending on which prerequisite files caused the update, and such cases are rare.
Just as the documentation says, double-colon rules are rarely very useful. They are a nice, little way of not naming the individual targets of a composite phony target (like all::), but not really necessary in this role. I can only form one contrived example where they are necessary:
Suppose you have a logfile L that is concatenated from several other logfiles L1, L2, .... You formulate a number of double-colon rules like:
L :: L1
cat $< >> $# && rm $<
L :: L2
cat $< >> $# && rm $<
Nowadays in GNU make, you would of course use $^ for this kind of magic, but it is listed as an inspired feature on GNU make's feature tab.
I'll contribute a simple example to hopefully make the usage clear:
Experiment with the following makefile:
a.faux:: dep1.fake
$(info run a dep1.fake)
touch a.faux
a.faux:: dep2.fake
$(info run a dep2.fake)
touch a.faux
dep1.fake:
touch dep1.fake
dep2.fake:
touch dep2.fake
Run make a.faux, it will causes dep1.fake and dep2.fake to run. Delete dep1.fake and run make a.faux again, only dep1.fake will run.

Resources