What does it mean to have a rule specified as follows?
foo: bar : baz
I understand that foo is a target, bar and baz are prerequisites but why there is another colon between bar and baz - what's the meaning of that colon?
The feature you are thinking of is a static pattern rule, and the syntax you give: foo : bar : baz is illegal; the bar part must be a pattern (that is, it must contain a % character).
Tripleee gives a reasonable explanation, except the statement when we build foo, bar depends on baz is somewhat confusing. What a static pattern rule means is that for each word in targets, create a new explicit rule where the target is the result of applying the pattern pattern to that word with the prerequisites prerequisites.
The general syntax is
targets: pattern: prerequisites
So this -- grossly oversimplified -- example of yours says, basically, when we build foo, bar depends on baz. However, the second argument needs to be a pattern rule, so your example is in fact a syntax error.
A more useful and correct example would be along the lines of
$(OBJS): %.o: ick.h
which says that if you are building one of OBJS, their .o file depends on ick.h.
Related
I thought I understood that % pattern matching:
%.o : %.c
#...
...was equivalent to "explicitly" writing the targets' rules:
f1.o : f1.c
#...
f2.o : f2.c
#...
(assuming those are the only .c files)
I also know that writing multiple rules for the same explicit target results in the rule being overwritten by the last defined rule:
r :
#1
r :
#2
(make outputs #2)
So, how exactly does make resolve the Makefile below?
foo : bar
bar :
#bar
% : %.c
#%
When bar.c is the only .c file in the directory (or there's none), it outputs:
#bar
If there's only foo and foo.c (and the Makefile):
#bar
#%
I wasn't sure what to expect when there was a bar.c file, but I thought when there wasn't that the only "command" being run would be #bar.
So, how are these rules/dependencies being resolved like this?
The reason that I'm interested is because this implicit/explicit "double-rule" syntax seems essential to understanding how -M and include work to automate header dependencies, for example:
a.out: main.o
g++ main.o
%.o: %.cpp
g++ $< -c
main.o: main.cpp foo.h # <-- what *.d files look like
...causes desired behaviour like:
a.out: main.o
g++ main.o
main.o: main.cpp foo.h
g++ $< -c
I thought I understood that % pattern matching ... was equivalent to "explicitly" writing the targets ... (assuming those are the only .c files)
That's not right.
A pattern rule is a template that tells make how it CAN build a target. Pattern rules are only used if there's no explicit rule for that target already. A pattern rule doesn't say "go find all files that match this pattern and create explicit rules for them". It says, "if you find you need to build a target but you don't have any explicit rule already, and the target matches this pattern, then here's how you can build it".
For example, if you have a makefile that contains ONLY pattern rules, even if those pattern rules match existing files, and you just type make, you'll get a message that make has nothing to do. That's because you've not asked make to build anything, you just told make HOW to build something.
I also know that writing multiple rules for the same explicit target results in the rule being overwritten by the last defined rule
Of course, you will get a warning if you do this about overwriting an existing recipe.
It's important to understand that you can have as many different lines adding new prerequisites to a target as you like. It's not until you create a recipe that you have created an explicit rule. Until then, there's no actual rule that matches the target.
On top of MadScientist's expert answer, I thought I'd explain how it applies to both outputs for the Makefile (which might be useful for make beginners like me):
foo: bar
bar :
#bar
% : %.c
#%
#bar
When there's no bar file:
bar :
#bar
...then bar is a "non-file" (phony) target. A phony target with no prerequisites always executes the recipe - as opposed to a file target where no prerequisites means that the target never has its recipe executed (not sure why this doesn't result in warnings). So, ironically, when there's no bar file, we see #bar output, otherwise we don't.
#%
As MadScientist says in his answer, % : %.c can never match bar/bar.c because there's an explicit rule for bar (ie. one with a recipe). However, we can use the recipe in
% : %.c
#%
... if we have the files foo/foo.c. This is because foo : bar isn't an explicit rule (has no recipe). The Makefile becomes equivalent to:
foo: bar
bar :
#bar
foo : foo.c
#%
...which is equivalent to:
foo: bar foo.c
#%
bar :
#bar
So make will output #% if there's no bar file, or if foo's timestamp is older than either bar or foo.c.
#bar
#%
To work out the combination of files we need to get both #bar and #%, we use our logic from the #bar section (above) which is simpler: We cannot have a bar file. Looking at the #% section, we see that if we have no bar file then we still need both foo and foo.c files (but timestamps won't matter). So the directory will be: foo, foo.c, Makefile, plus any other file except for bar.
Say I have the following set of inputs:
list = foo \
bar \
baz
And say I have a rule such as follows:
$(somedir)/%:
# Do something here
I know I am able to invoke the rule by statically defining the target and its dependency:
$(somedir)/foo : foo
$(somedir)/bar : bar
$(somedir)/baz : baz
However, would there be a way to apply this rule to an evergrowing $(list) of inputs rather than having to statically define them all?
To be more specific, I am looking for a way to run a rule for each input and get an output (which is $(somedir)/input). Is this possible in Make?
Well, not sure I understand all the details but it seems to me that pattern rules are exactly what you need:
$(somedir)/%: %
# your recipe
This tells make that any $(somedir)/foo depends on foo and is built by the given recipe. Of course, you will also need to tell make which target you want to build:
make somedir=there there/foo there/bar
Bonus: if you know the list you can add a phony target to build them all at once:
list = foo bar baz
.PHONY: all
all: $(addprefix $(somedir)/,$(list))
$(somedir)/%: %
# your recipe
Second bonus: to help writing your recipe you can use automatic variables: $# expands as the target, $< as the first prerequisite, $^ as all prerequisites, etc. So your recipe could resemble this:
$(somedir)/%: %
build $# from $<
I have a couple of rules which are parametrised as follows:
.SECONDEXPANSION:
NAME=default
foo: x-$$(NAME)
bar: NAME=bar
bar: foo
baz: NAME=baz
baz: foo
x-%:
#echo building $#
I would expect the following output when running make bar:
$ make bar
building x-bar
But I see:
$ make bar
building x-default
Is there a way to delay expansion in a rules' prerequisites until after it is being invoked so I can parametrize the rules like this? I would like to avoid using define ... endef etc. because my rules are quite complicated and having another level of $$ in there would really hurt readability.
This was a bug in make. Fixed in make 4.4. It yields the output you expected:
# make bar
building x-bar
.PHONY: foo bar baz
all: foo bar baz foo bar
# #=$#
# ?=$?
# <=$<
# ^=$^
# +=$+
Here is the output of this:
# #=all
# ?=foo bar baz
# <=foo
# ^=foo bar baz
# +=foo bar baz foo bar
If if comment first line as:
#.PHONY: foo bar baz
Then output is:
make: *** No rule to make target `foo', needed by `all'. Stop.
i have two question:
1) Why make does not complain for a rule in first case when "foo bar and baz" are declared PHONY.
2) I started commands with a pound(#). Why these commands are not treated as a comment.
Etan has the right info in his comments. Just to be a little more verbose:
1) Declaring a target PHONY creates it as a target inside make. So thereafter, if you list it as a prerequisite, make knows about it just as if you'd written foo: as a target. It could be argued this is a bug in make; I'm not sure, but that's how it works.
2) The important detail from Etan's answer is that if there's a line in your makefile [1] that starts with a TAB, make will send it to the shell. Make doesn't try to interpret the line, even to see if it's a comment or not (other than expanding variables/functions of course). Whatever you write, is sent to the shell.
[1] "in a target context", which is hard to describe concretely... best bet is to never use TAB unless you're trying to write a recipe line.
I've two targets foo and bar. Neither depend on the other, but if bar has to be rebuilt, it has to be done before foo. They are what gnu-make calls phony targets, their rules have always to be executed when they are specified.
Currently, we express a main target which depends on both like this:
# user level targets
all: bar
#$(MAKE) foo
#echo all
alt: foo
#echo alt
# internal targets
foo:
#echo foo
bar: qux
#echo bar
qux:
#echo qux
#touch qux
and we have the required behavior: if qux is not up-to-date: make bar outputs qux bar foo all (in that order) and make alt outputs foo alt; if qux is up-to-date, make bar output bar foo all and make alt outputs foo alt.
This is increasingly uncomfortable as foo has to be handled specifically (all targets which depend on both have to be handled that way, foo can't be put in a variable describing dependencies if bar is also there, the submake is itself an issue and the command line has to be maintained to pass additional variables). We now have another target which has to be handled in the same way and I'm looking for other, more convenient, ways to handle the structure.
Note 1 : In practice, I'm currently using only gnu-make but the only known dependency on a gnu-make extension over POSIX is the possibility to include files (which is quite widely available). I'd prefer something which keep the current state (i.e. widely supported constructs), but if it is not possible, the use of a gnu-make only extension is acceptable.
Note 2: gnu-make has a notion of order-only-prerequisites, but it apparently doesn't provide what we need. With
# user level targets
all: bar foo
#echo all
alt: foo
#echo alt
# internal targets
foo: | bar
#echo foo
bar:
#echo bar
make alt also build bar (if a file bar exist, its date doesn't influence the decision of rebuilding foo, which is the documented behavior).
Note 3: The more I think about it, the less I think it is possible to solve this problem with make without using a recursive call. It seems to me that it need two passes on the dependency graph, one to determine what has to be built, one to determine the ordering and I know nothing in make behavior which can't be done with a one pass algorithm.
Hmmm, how about this hack (for a hack it undoubtedly is :-)).
Basically, you could run make -d -n plus your command arguments. The output will contain several lines like Must remake target 'clean'. This information tells you whether this run of make will attempt to build both foo and bar. If this turns out to be the case, just add a rule to cause the serialisation you want.
A sketch:
this := $(lastword ${MAKEFILE_LIST})
ifndef DONTRECURSE
targets-that-will-get-remade := $(patsubst %',%,$(shell ${MAKE} -f ${this} ${MAKECMDGOALS} --debug=b -n DONTRECURSE=nosiree | grep -Po "Must remake target '\K.*'"))
endif
ifeq (bar foo,$(sort $(filter bar foo,${targets-that-will-get-remade})))
foo: bar
endif
.PHONY: foo bar
foo bar:
sleep 3
: $#
So, you run make. DONTRECURSE is not set so the $(shell …) runs. That runs make a second time with the same makefile and goals, but adds the -d (debug) and -n (don't actually run the recipes) flags. DONTRECURSE is set to prevent a third copy of make running.
The expansion of all that is a list of the targets this run of make will attempt to build on this run. (Extracting the target names is pretty tiresome—there is probably a cleaner way.)
If this list of targets includes both foo and bar, simply add a foo: bar dependency. Job done. The sleep 3 lines show this serialisation working when you use -j4 (say).