Order of processing components in makefile - makefile

In a makefile, the dependency line is of the form -
abc: x y z
All three of the components (x,y,z) are themselves targets in dependency lines further down in the makefile.
If make abc is invoked, in what order will the three targets x,y,z be executed?

By default, the order of execution is the same as specified in the prerequisites list, unless there are any dependencies defined between these prerequisites.
abc: x y z
The order is x y z.
abc: x y z
y : z
The order would be x z y.
But ideally, you should design your Makefiles so that it wouldn't rely on the order in which prerequisites are specified. That is, if y should be executed after z, there must be a y : z dependence.
And keep in mind that GNU Make can execute some recipes in parallel, see Mat's answer.

You really shouldn't depend on the order in which they are executed - all else being equal, all three recipes for those prerequisites could run in parallel.
The only hard rule is that all prerequisites must be met before the target recipe is run.
If there are no dependencies between x, y and z, and no parallel execution, GNU make appears to run them in the order you specified them, but this is not guaranteed in the docs.

The POSIX description of make includes a rationale which says:
The make utilities in most historical implementations process the prerequisites of a target in left-to-right order, and the makefile format requires this. It supports the standard idiom used in many makefiles that produce yacc programs; for example:
foo: y.tab.o lex.o main.o
$(CC) $(CFLAGS) -o $# t.tab.o lex.o main.o
In this example, if make chose any arbitrary order, the lex.o might not be made with the correct y.tab.h. Although there may be better ways to express this relationship, it is widely used historically. Implementations that desire to update prerequisites in parallel should require an explicit extension to make or the makefile format to accomplish it, as described previously.
(I believe the t.tab.o in the $(CC) line is a typo for y.tab.o, but that is what the rationale actually says.)
Thus, the observed behaviour that pre-requisites are processed from left to right has validation here, though it is only in the Rationale section, not in the main description. The Rationale also mentions issues with parallel make etc.

From https://stackoverflow.com/a/22638294/636849, you can add the pipe symbol:
abc: | x y z
From make manual:
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

Related

GNU Make: Ensure existence of prerequisite and disable implicit rule search

Question:
How can I disable implicit rule searches on a prerequisite while still ensuring that the prerequisite actually exists?
Background:
Consider the following initial Makefile:
b: a
#echo MAKING B
cp a b
a is a file which is required in order to make b. If the file a exists, make b runs successfully. If it doesn't exist, we obtain the following error:
make: *** No rule to make target `a', needed by `b'. Stop.`
This is exactly what we expected, however on inspecting the output of make --debug=a b, we see that even when a exists, make is searching through pre-defined implicit rules fitting a in order to see whether it can be re-made. For example, if the file a.c happened to exist, then make would try to compile a.c to produce the file a. To prevent this, we define an explicit rule for a with an empty recipe. This gives us the updated Makefile:
a: ;
b: a
#echo MAKING B
cp a b
The problem now is that the recipe for make b runs even if a does not exist, which results in a failure. Is there any other way to indicate that a should exist, while not searching for implicit rules to build a? I would like to do this without giving a recipe for a which checks its existence.
I'll try to sum up state of our discussion so far. Perhaps someone still pop's up with another/better insight.
Besides the option also mentioned in the question itself (see bellow for explainer on latest iteration for this approach):
a:
$(error missing file "$#")
b: a
#echo MAKING B
cp a b
In theory it should be possible to disable implicit pattern rule altogether or for specific (set) of target(s) by either defining a no recipe target rule (% : %.c) or defining a static pattern rule (a: % : %.c). Nonetheless the resulting behavior, in case there is an a.c file, seems to be the same as with an empty rule for a:. I.e. make b just proceeds without file a being present (and we'd later fail trying to access it).
Since at least some of the implicit rule seem to be implemented as suffix rules, it's possible to disable consideration of inputs like a.c by purging list of default suffices:
.SUFFIXES:
Or inhibit use of implicit built-in rules altogether by invoking make with -r (or --no-builtin-rules) option. These however are rather heavy handed as they impact processing of all the rules across the Makefile.
To work the comment in:
as mentioned disabling couple of the built in rules for C compilation would appear to yield the desired result, namely:
% : %.c
% : %.o
Would result with a.c present and no a in make: *** No rule to make target 'a', needed by 'b'. Stop.
However (like -r) it's rather intrusive as in all other targets relying on the implicit rule would be impacted. While at the same time it's not as very far reaching, because it does not cover other cases like a.C, a.cpp, a,v,...
Static rule should be able to replace pattern rules where applicable (a more specific rule being applied over the more generic one when matching). But indeed limiting its to a single target does basically put it on par with just a specific a: rule.
I am actually not sure what the rest of the tree looks like and what all possible build steps could occur. With current understanding I would still gravitate to explicit target with file existence check should files with colliding names be a possibility and concern.
Explanation for the latest version of simple failing rule:
As #Stein followed up on the topic, he actually very helpfully pointed out: Simple (always) failing rule for "building" a is perfectly sufficient. If a file of that name (a) exists, the rule for target a never gets to run its recipe. For the case the file is not there, we can just have a recipe that fails with an error message.

Recipe that produces multiple targets

In our makefile, we have one recipe that links together all our object and library files to make an executable (an .elf file). As a side effect, this step also produces a map-file and an Intel .hex file:
$(ELF_FILE) : <list of dependencies here>
<linker command line>
Until now, since we never actually had a $(MAP_FILE) or a $(HEX_FILE) target, when ever another target depended on one of the $(ELF_FILE)'s side products, we simply declared it to be dependent on $(ELF_FILE), even if the recipe of that target didn't want to access the $(ELF_FILE) itself at all. For instance:
# Target that needs map-file, which is a side product of the $(ELF_FILE) target.
$(TARGET_THAT_NEEDS_MAP_FILE) : $(ELF_FILE)
<build-recipe>
# Target that needs hex-file, which is also a side product of the $(ELF_FILE) target.
$(TARGET_THAT_NEEDS_HEX_FILE) : $(ELF_FILE)
<build-recipe>
We have recently found out that a recipe can be used for more than one target, like so:
$(MAP_FILE) $(HEX_FILE) $(ELF_FILE) : <list of dependencies here>
<linker command line>
With this new-found knowledge, we figured we could get rid of the above "hack" and just directly state each target's direct dependencies:
$(TARGET_THAT_NEEDS_MAP_FILE) : $(MAP_FILE)
<build-recipe>
$(TARGET_THAT_NEEDS_HEX_FILE) : $(HEX_FILE)
<build-recipe>
Having implemented these changes, we now observe an odd effect that makes us suspect that we've either misunderstood this multiple-targets-one-recipe feature of make, or we're not using it correctly. The odd effect is that the recipe that produces the .elf, .map and .hex files now appears to run twice. This doesn't seem to have caused any immediate problems, but it does seem to indicate that something is fishy here. So my question, can our new approach work at all, or should we stick to the hack I described above?
EDIT: We're running our make in a multi-threaded manner (i.e. with -j).
It might be that when make is trying to update a target (whether it is $(MAP_FILE), $(HEX_FILE) or $(ELF_FILE), it does not know that its recipe will also update another target, therefore it starts a recipe for that one too, even if it's the same.
Of course, that would only happen when using the -j option. (Did you had the possibility to try without ?)
To illustrate :
$(TARGET): $(ELF_FILE) $(MAP_FILE)
<update target>
Here make will try to update $(ELF_FILE) and $(MAP_FILE) and fire the recipe twice. (That should also applies if the dependencies are on different target, as long as the targets are updated by a one execution of make and that there is no bottlenecks between them.
I'm not completely sure about that, though, make might be able to know that this is the same recipe.
======
This answer might be of use to you.
Specifically :
However, if your output files and your input file share a common base,
you CAN write a pattern rule like this:
%.foo %.bar %.baz : %.boz ; $(BUILDIT)
Strangely, for implicit rules with multiple targets GNU make assumes
that a single invocation of the recipe WILL build all the targets, and it will behave exactly as you want.
MadScientist
It refers to that part of the make manual :
Pattern rules may have more than one target. Unlike normal rules, this
does not act as many different rules with the same prerequisites and
recipe. If a pattern rule has multiple targets, make knows that the
rule’s recipe is responsible for making all of the targets. The recipe
is executed only once to make all the targets. When searching for a
pattern rule to match a target, the target patterns of a rule other
than the one that matches the target in need of a rule are incidental:
make worries only about giving a recipe and prerequisites to the file
presently in question. However, when this file’s recipe is run, the
other targets are marked as having been updated themselves.
EDIT:
Gnu Make has now gained a feature that would support this usecase (in version 4.3) : grouped explicit targets. It allows make to be aware that one recipe generate several targets, and it used like this (from the gnu make manual) :
foo bar biz &: baz boz
echo $^ > foo
echo $^ > bar
echo $^ > biz
foo, bar, and biz are generated by this rule (note the use of &: instead of :.
Full documentation : https://www.gnu.org/software/make/manual/html_node/Multiple-Targets.html ("Rules with Grouped Targets")

Prioritizing pattern rules in Make

I have (roughly) this Makefile:
.PHONY: all
.SUFFIXES:
OUT = /www/web
all: $(OUT)/index.html
# rule 1
%.html: %.in
build_html $< $#
# rule 2
$(OUT)/%: %
cp $< $#
This Makefile has a problem, since there are two different ways to build $(OUT)/index.html:
build ./index.html (rule 1), then copy it to $(OUT) (rule 2).
copy ./index.in to $(OUT) (rule 2), then build $(OUT)/index.html (rule 1).
I want make to always prefer option 1. How can I indicate that there is a preferred order between these two pattern rules?
(I can think of a few hacky ways to accomplish it for this particular case, but I want a solution that is as general as possible---for instance, changing the pattern of rule 2 to $(OUT)/%.html: %.html will fix the problem, but loses generality since I need to repeat myself if I want to handle other kinds of files in the same way later.)
A quote from the GNU Makefile Manual:
It is possible that more than one pattern rule will meet these criteria. In that case, make will choose the rule with the shortest stem (that is, the pattern that matches most specifically). If more than one pattern rule has the shortest stem, make will choose the first one found in the makefile.
So, you can try to create rules which ensure shorter stems to take priority. Alternatively, you could use static pattern rules to limit the scope of what gets copied where, as so:
%.html: %.in
build_html $# $<
$(expected_out) : (OBJS)/% : %
cp $# $<
and then prepopulate $(expected_out) with what you want in there. Finally, you can add:
$(OUT)/index.html : index.html
somewhere in your makefile, as make prefers the 'shortest path' to building an object, which would only be one pattern rule in this case.
While #John's answer best fits my use-case (I know exactly what files belong in $(OUT)), there is also an alternative solution: mark the desired intermediate file as "precious".
.PRECIOUS: index.html
This will also instruct Make not to delete index.html, which it would otherwise do for you.
This works thanks to Make's algorithm for choosing implicit rules. Make favors rules whose dependencies exist or ought to exist, and a file "ought to exist" if it has an explicit rule or is a dependency of another rule. This applies even if it is a dependency of a special target like .SECONDARY, .INTERMEDIATE, or .PRECIOUS. For more info, also see the manual section on "Chains of Implicit Rules".

Two assignments on same line in GNU makefile

A certain makefile (namely, the otherlibs/num/Makefile in the OCaml 4.2 distribution) has the following line :
EXTRACFLAGS=-DBNG_ARCH_$(BNG_ARCH) -DBNG_ASM_LEVEL=$(BNG_ASM_LEVEL)
I am surprised to see two assignments on the same line here. What does it mean ? Is it the same as
EXTRACFLAGS=-DBNG_ARCH_$(BNG_ARCH)
-DBNG_ASM_LEVEL=$(BNG_ASM_LEVEL)
I did not find anything about that in the GNU make manual, maybe I am unaware of the right keyword to search this.
There are not two assignments here. The line assigns the definition:
-DBNG_ARCH_$(BNG_ARCH) -DBNG_ASM_LEVEL=$(BNG_ASM_LEVEL)
to the make variable EXTRACFLAGS. The value appears to consist
of flags that are to be passed to some invocation of the C preprocessor to
define macros BNG_ARCH_$(BNG_ARCH) and BNG_ASM_LEVEL. E.g. as
in a make recipe:
$(CPP) $(EXTRACFLAGS) ...
Which, supposing the make assignments:
BNG_ARCH = foo
BNG_ASM_LEVEL = bar
would expand to:
cpp -DBNG_ARCH_foo -DBNG_ASM_LEVEL=bar ...
OP comments:
So you might say that = is "left-associative", the leftmost = sign is the one that really gets executed. Is this documented somewhere in the manual?
From my frequent, but far from exhaustive resorts to manual I can't say it is documented. Somebody
may know better. There is no formal grammar there, but it is everywhere illustrated that the definition of a variable extends from the
start of the non-whitespace text following =, := or ?= to the end of the (possibly \-extended)
logical line. You may satisfied on the point by running the makefile:
.PHONY: all
x = X y = Y
all:
#echo [$(x)]
#echo [$(y)]
which prints:
[X y = Y]
[]
Assignment signs within a make-definition are not assignments, they're just characters in the definition.

How such makefile works? (is it normal?)

I encountered such pattern in makefile
CXXOBJ = f1.o f2.o f3.o
$(CXXOBJ): %.o: %.cpp
g++ -c $< -o $#
f1.o: f1.cpp f1.hpp f2.hpp
f2.o: f2.cpp f2.hpp f3.hpp macros.h
f3.o: f3.cpp f3.hpp
It works (at least with GNU make 4.0).
It uses generic recipe from 4th line,
but in addition uses dependencies defined at the bottom.
Questions
Is it standard make behavior? (or is it specific to GNU-make?)
Is it standard way to write make file? (i.e. are people usualy doing it this way or is it something 'exotic'?)
How exactly does it work?
How does make combine 2 distinct rules for same file? (just append dependency list or something more?)
(I was browsing through GNU-make manual, but could not find relevant part)
This is called static pattern rules (https://www.gnu.org/software/make/manual/html_node/Static-Usage.html). It is specific to GNU make. It might be useful when different targets require different recipes to build, but match the same pattern.
As for third question, there are no distinct rules for the same file. Everything is quite well defined, each target have corresponding .cpp file.
GNU Make manual:
One file can be the target of several rules. All the dependencies
mentioned in all the rules are merged into one list of dependencies
for the target....
There can only be one set of commands to be executed for a file. If
more than one rule gives commands for the same file, make uses the
last set given and prints an error message...

Resources