Gnu make - Force "Remake" of prerequisite - makefile

Makefile-snippet:
x:
# echo reached $(#)
a: x
b: a x
make b; on commandline echoes only once: how to get x executed every time it is referenced (2 times in this example); in other words: how to make make forget that x has already been done as a prerequisite of a, so it runs as a prerequisite of b too ?
found Execute make prerequisite every time but maybe there are other approaches.
thanks in advance.

Related

Make should not rebuild deep dependencies

I have a build procedure roughly described by the following Makefile example:
a: b
#echo "Build a, just using b. Don't care about c."
touch a
b: c
#echo "Constructing b from c is cheap..."
touch b
#echo "Once accomplished, I no longer need c."
c:
#echo "Constructing c is very expensive..."
#echo "Work work work..."
touch c
clean:
$(RM) a b c
example: clean
make a
$(RM) c
make a
The point is: I need c to build b, but once I have b, I never again need c. When I do make example, make makes c, b, and a (as expected), deletes c, and then, in the last make a invocation, just remakes c (and does NOT re-make b and a, even though, I'd have thought they were stale now). But, since my goal is a and b hasn't changed, I don't want to remake c. Forget about it! Who cares! a should be considered up-to-date.
Another peculiar thing, is that when I
make a
rm c
make a
(rather than make example), in the second invocation make rebuilds everything (while in make example the second invocation just rebuilds c).
How do I prevent make from building c when its goal is a and all of a's immediate prerequisites exist and is fresher than they are (a isn't stale compared to b), even though the prerequisites of the prerequisites do not?
Edit: I think that what I may want is to treat every file as old (eg. with --old-file) unless that file doesn't exist.
It looks like you want make to treat the file c as an intermediate file, a file that does not have any importance to you other than as an intermediate result when generating another file or other files. This concept is explained in section 10.4 Chains of Implicit Rules of the manual. Since your example does not use any implicit rules, you can manually mark your file c as .INTERMEDIATE.
This makefile shows c as an intermediate file.
a: b
#echo "Build a, just using b. Dont care about c."
touch a
b: c
#echo "Constructing b from c is cheap..."
touch b
#echo "Once accomplished, I no longer need c."
c: d
#echo "Constructing c is very expensive..."
#echo "Work work work..."
touch c
.INTERMEDIATE: c
.PRECIOUS: c
I added a file d, based on your comment, although it is not needed for this example to work.
Before invoking make, the file d has to exist, it is the starting point of the chain. When invoking make, the following happens:
$ touch d
$ make
Constructing c is very expensive...
Work work work...
touch c
Constructing b from c is cheap...
touch b
Once accomplished, I no longer need c.
Build a, just using b. Dont care about c.
touch a
Now deleting c will not have any impact on the build:
$ rm c
$ make
make: `a' is up to date.
Other than that, the update behavior based on dependencies is "the same as usual".
The .PRECIOUS target is optional. It is a built-in that instructs make not to delete the intermediate file named c. You can see for yourself what happens if you remove that line.
b might be built from c, but you don't want to tell Make that b depends on c — if b merely exists, then that's good enough. So you might write b's recipe as
b:
$(MAKE) c
#echo "Constructing b from c is cheap..."
touch b
#echo "Once accomplished, I no longer need c."
or if c is only used in making b, you could just fold the commands for making c into the recipe for b and not expose the existence of c to Make at all.
Maybe there are more elegant ways of expressing this, without invoking sub-makes. And if c has some prerequisites that would cause it to be rebuilt if they were updated, I guess they would need to be listed as reprequisites of b as well.

Order-only prerequisites not working correctly in GNU make?

I have a problem with order-only prerequisites. These do not execute first at all. Am I mis-understanding the way order-only prerequisites work?
The following make script:
.PHONY: mefirst mefirst2
mefirst:
#echo "I'm first!"
mefirst2:
#echo "I'm first too!"
normaltarget: normaltarget2 | mefirst2
#echo "normaltarget done"
normaltarget2: a b c
#echo "normaltarget2 done"
helloworld: normaltarget | mefirst
#echo "helloworld done"
.DEFAULT_GOAL := go
go: helloworld
#echo "go done"
a:
#echo a
b:
#echo b
c:
#echo c
...prints out the following:
a
b
c
normaltarget2 done
I'm first too!
normaltarget done
I'm first!
helloworld done
go done
...instead of what I would expect:
I'm first!
I'm first too!
a
b
c
normaltarget2 done
normaltarget done
helloworld done
go done
What am I doing wrong?
Am I mis-understanding the way order-only prerequisites work?
Yes, that is what it looks like.
The name "order-only" is somewhat confusing. The prerequisites behind the | are called "order-only prerequisites" not because they change the order of recipe execution inside the list of prerequisites for a single target, but because their only purpose is to have certain targets created before others, like a bootstrap. As accurately explained by user bobbogo below ( -- thanks for correcting): if make decides to rebuild a prerequisite of a target, it will run the recipe for that prerequisite. Now, for an ordinary prerequisite this update implies that the target is now out-of-date, and make will have to run the target's recipe. For an order-only prerequisite on the other hand, make does not mark the target as needing an update.
For example see the section Types of Prerequisites for a use case where a directory should be created before the objects in that directory are created.
Take this example makefile:
a: b
touch a
b: c
touch b
c:
touch c
x: | y
touch x
y: | z
touch y
z:
touch z
As you can see, b and c are normal prerequisites of a and b, whereas y and z are order-only prerequisites of x and y. Starting from a clean slate, they look the same:
:~$ make a
touch c
touch b
touch a
:~$ make x
touch z
touch y
touch x
:~$ make a
make: `a' is up to date.
:~$ make x
make: `x' is up to date.
However, if we now manually "update" the prerequisites at the end of the chain (c and z), we see the difference:
:~$ touch c
:~$ make a
touch b
touch a
:~$ touch z
:~$ make x
make: `x' is up to date.
This shows how order-only prerequisites that exist do not invalidate any targets, independent of their time-stamp. Deleting the order-only target does result in rebuilding though (but only rebuilding of that missing file):
:~$ rm c
:~$ make a
touch c
touch b
touch a
:~$ rm z
:~$ make x
touch z
Having that said, the correct way to change the order in which your recipes are run is by correcting the dependencies between the targets. For example, if you want mefirst to be built before a, then you need to make mefirst a prerequisite for a, as in
a: mefirst
#echo a
It is not possible to give the entire solution to your question since you did not describe in detail in which order you expect recipes to run.
There is a shortcut to your answer which is not the solution but still interesting to know. Although not documented, it seems that the prerequisites of a single target are processed in the order that they appear. The | sign does not change that. In your simple case, you can take advantage of that to achieve the output that you are looking for:
normaltarget: mefirst2 normaltarget2
#echo "normaltarget done"
and
helloworld: mefirst normaltarget
#echo "helloworld done"
However, as pointed out by yourself, this "solution" breaks as soon as the -j flag is used to run recipes in parallel. Also, as pointed out by user bobbogo, relying on this ordering mechanism is bad practice. Introducing new dependencies can interfere with the ordering. So don't do this :-)

Understanding Makefile Syntax and Variables

I'm reading a big Makefile, part of which I don't understand:
$(IREJECTION): $(IREJECTION:%$(MACH64).o=%.cpp)
$(CPP) $(CPPDLIBOPTS) -c $(#:%$(MACH64).o=%.cpp) -o $#
In this script (note that I removed unnecessary variables to avoid verbosity), what does the following mean
$(IREJECTION:%$(MACH64).o=%.cpp) (on the first line)
$(#:%$(MACH64).o=%.cpp) ? (on the second line)
Also, what does this form A: B mean? As in :
$(IREJECTION): $(IREJECTION:%$(MACH64).o=%.cpp) #on the first line
<---- A ----> <------------ B ---------------> #first instance of A: B
<--- A ----> <-------- B ------> #second instance of A: B
As you see, there are two instances of the form A:B — the second one is inside B itself. I see similar thing here as well:
$(#:%$(MACH64).o=%.cpp) #on the second line
<A> <---------B------->
Please help me understand this.
You got quite complex example I think. It has many things in it.
Rule / Recipe
A: B
<command>
A - target
B - dependency
<command> - command to be executed to build A ("Recipe")
target: dependency is called a 'rule'.
So all in all, above example is 'rule' with appropriate 'recipe'.
(to make A, which depends on B, one needs to execute <command>)
make compares modifications dates of B and A. If B is newer, then it executes <command>
Variables
$(IREJECTION) is make's variable (it should be defined somewhere before in the file, like IREJECTION:=somefile.o)
During make execution $(IREJECTION) is replaced to actual value of the variable.
Variable substitution
From link below:
$(var:a=b) <..> take the value of the variable var, replace every 'a' at the end of a word with 'b' in that value, and substitute the resulting string.
And:
For example:
foo := a.o b.o c.o
bar := $(foo:%.o=%.c)
sets bar to a.c b.c c.c.
In your case $(IREJECTION:%$(MACH64).o=%.cpp), it takes variable named IREJECTION, tries to find $(MACH64).o (which also references variable MACH64) at the end of the word and replace it with .cpp.
Automatic variable
$# is called automatic variable.
It is reference to the 'target'.
Futher reading
http://www.gnu.org/software/make/manual/make.html
A: B meant that you add a make target A that depends on B. That means when B was changed, it has to be run before A is done.
You can use the target A by calling make A.
I'll go tep by step:
lets say you have some object file irejection.mach64.o and the source file irejection.cpp
to generate object from source you typically write a rule smth like
irejection.mach64.o : irejection.cpp # means target : dependencies
$(CC) irejection.cpp -o $# # $# is a special variable - the target (output)
Now lets say $(MACH64) is .mach64 and $(IREJECTION) is irejection$(MACH64).o, ie irejection.mach64.o
$(IREJECTION:%$(MACH64).o=%.cpp) will expand to irejection.cpp
$(#:%$(MACH64).o=%.cpp) will expand to the same, since $# is $(IREJECTION)
In essence, given object file target with a architecture extensions, rewrite the file name to its source file counterpart.
Seems unncessearily convoluted to me tho. Cleaner way would be smth like:
%$(MACH64).o : %.cpp
$(CC) -c $# $<
% are "wildcards", $< is the first dependency, $# is the output
see: http://www.gnu.org/software/make/manual/make.html#Automatic-Variables
http://www.gnu.org/software/make/manual/make.html#Pattern-Rules

Why does make not consider a target without recipe out of date when updated by a PHONY dependency?

.PHONY: b
c: a
#touch c
#echo "Changed"
a: b
b:
#date +%s > a
Running make with the sample make file causes "Changed" to be printed the 1st time it is run; but "Changed" is only printed then on the 3rd, 5th, etc execution. This is because make doesn't seem to recognize that executing the recipe for target "b" updates a.
Changing the rule with "a" as the target into an empty recipe causes "Changed" to be printed for each time make is run (as you would expect - where phony targets are always considered "out of date"). E.g.
a: b ;
Make should skip the implicit rule search for PHONY targets, but "a" is not PHONY. If no implicit rule is found for "a", is make correct to not consider that "a" may have been changed by its PHONY dependency "b"?
Make can't analyze the effects of commands, so it is the user's responsibility to organize the rules correctly.
Consider a slightly different case:
d: c b
c: a
#touch c
#echo "Changed"
a:
b:
#date +%s > a
This has the same behavior as your example; there's no way Make could be expected to know that c "really" depends on b. The author of the makefile is at fault.
Now the way it should be written:
c: a
#touch c
#echo "Changed"
.PHONY: a
a:
#date +%s > a
The a rule modifies the file a (and PHONY is there just to force the a rule to run). This is the way to tell make that the #date ... command modifies a. This makefile works correctly.
Your example is midway between these two. If a rule modifies a file which is the target of another rule, the makefile is badly organized, and Make is not at fault. Yes, Make could assume that a target that depends on a PHONY rule may have been updated when that rule is run, but it could just as well assume that any target may have been updated when any rule is run. And if Make were that paranoid, it wouldn't be very efficient.

Order of processing components in 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

Resources