I have a main Makefile that calls Makefiles placed in subfolders. For testing purposes I would like to add Match-Anything rule at the end of main Makefile.
This rule would be:
%:
make -e -C subdir $#
Are there any contrarguments for such a rule?
I think you meant "con", as in "pro or con", not "cont". "Con" is short for the Latin "contra".
For your question, the downside of adding a new "match anything" rule is that any file that doesn't exist, will try to be created using this rule. For example suppose you run include foo.mk and foo.mk doesn't exist... make will attempt to build foo.mk by running your rule. Basically it can be confusing. It's possible there could be some performance impact; if you run make -d and examine it you should see if your match-anything rule is being used at all during a normal build. I'm not sure if there are any other serious downsides.
By the way you should always only use the make variable $(MAKE) when invoking a sub-make in a recipe; never use the raw make command.
Related
Using GNU make, I am trying to solve a problem similar to make recipe execute twice — that is, to have a Makefile recipe run twice. In my case, however, the recipe is run under the .SECONDEXPANSION target, and the two different runs will be called with different parameters to generate different versions of the output file from the same input file. That is, with input file foo, this example Makefile should be callable via make foo.pdf or make foo.expanded.pdf to build one .pdf file, or make all to build both .pdf files:
.PHONY: all
all: foo.pdf foo.expanded.pdf
.SECONDEXPANSION:
%.expanded.pdf %.pdf: %
#echo building $(basename $#)
Of the two solutions given in that answer, the first is unsuitable because it always runs the rule twice; I want it run twice when the user asks for it.
The second solution posted there is conceptually what I am looking for and have implemented in the above example Makefile, with only the small problem that it doesn't work: although the all target lists both .pdf files as dependencies, only one is built when make all is run.
Is there a way to tell GNU make to build two different files using the same rule under a .SECONDEXPANSION?
EDIT: Clarified in problem description that the same input file is used to build both versions of the output file, and modified sample Makefile to include this dependency.
EDIT: I would like a solution as scalable as possible; that is, it should work if the input filename contains dots, specifying additional output file foo.reduced.pdf should require only adjusting the targets and recipe as appropriate, etc. This limits performing string surgery that relies on the filenames appearing exactly as given in this narrow example (e.g., changing the rule to %.pdf: $$(firstword $$(subst ., ,$$*)) fails if the input file could be either foo or foo.bar).
You are probably looking for Pattern-specific Variable Values. Let's assume your recipe depends on a make variable named BUILDFLAGS that takes value normal by default and special for the "expanded" targets. Then this Makefile:
BUILDER := builder
BUILDFLAGS := normal
.PHONY: all
all: foo.pdf foo.expanded.pdf
%.expanded.pdf: BUILDFLAGS := special
%.pdf:
$(BUILDER) $(BUILDFLAGS) $#
should do about what you want with the same rule for all targets, plus one pattern-specific variable value declaration. Replace builder, normal and special with what makes sense in your case. Demo:
$ make foo.pdf
builder normal foo.pdf
$ make foo.expanded.pdf
builder special foo.expanded.pdf
$ make
builder normal foo.pdf
builder special foo.expanded.pdf
Your problem has nothing to do with .SECONDEXPANSION. You can just drop that and the problem will be the same.
Your problem is that you are using a pattern rule with multiple target patterns, and expecting that it works similar to an explicit rule with multiple targets. But it does not (and in fact you cannot have a rule with both pattern and explicit targets).
For a pattern rule with multiple target patterns, Make matches the same pattern to all the %, including multiple times in the targets, and then assumes that it just has to execute the recipe with that pattern once, and it will make all the matched targets.
In your case the best way is to use multiple rules (I changed your recipe because using echo as a Make recipe is a bad idea):
.PHONY: all
all: foo.expanded.pdf foo.pdf
RECIPE = touch $#
%.expanded.pdf:
$(RECIPE)
%.pdf:
$(RECIPE)
I have a Makefile with tons of targets and would like for a certain script to get executed first, irrespective of what target is being called. I like to call it a global prerequisite.
I do not want to create a target for the script and set it as a prerequisite for all existing targets (which, as I said aren't few). Besides, someone else could add a target in future and not add my script as a prerequisite for their target, so the global prerequisite would take care of that.
Does GNU-make provide for a means to achieve this?
Another approach:
-include dummy
.PHONY: dummy
dummy:
run-the-script
Make will always attempt to rebuild any file which the makefile attempts to include (if it is out of date or does not exist). In this case there is no such file, and the rule to build it runs the script and does nothing else.
There is a solution without modifying your existing Makefile (main difference with the answers pointed to by tripleee). Just create a makefile containing:
.PHONY: all
all:
pre-script
#$(MAKE) -f Makefile --no-print-directory $(MAKECMDGOALS) MAKE='$(MAKE) -f Makefile'
post-script
$(MAKECMDGOALS): all ;
The only drawback is that the pre- and post- scripts will always be run, even if there is nothing else to do. But they will not be run if you invoke make with one of the --dry-run options (other difference with the answers pointed to by tripleee).
If you read the Catalog of Rules section of the GNU Make manual, it turns out that one of the suffixes that it recognizes is .out and there is a built-in rule:
%.out: %
# commands to execute (built-in):
#rm -f $#
cp $< $#
This means that if you have a file xyz in a directory, you can create xyz.out by simply typing make xyz.out.
My question is (two variants of the same question):
Who benefits from this rule?
In what circumstances is this used by people?
Obviously, I'm asking because I managed to run foul of the rule. I had some rules like:
test.01: ${PROGRAM} ${DRIVER} test.01.tst test.01.out ${DATA.01}
${DRIVER} ${D_FLAGS} $#
where the name test.01 is a phony target, but one of the dependencies is test.01.out. When actively run (not using make -n; that works fine), this gives me lots of errors like:
make[1]: Circular test.01 <- test.01.out dependency dropped.
I also tried dropping the .out suffix with:
.SUFFIXES:
.SUFFIXES: .sh
and that didn't seem to neuter the .out rule like I expected. Is that an expected feature of GNU Make?
I guess I'm going to have to work around this bug feature of GNU Make by changing my suffix to .req or something similar, but it is a nuisance and I'm left puzzled about why the .out rule is part of the standard GNU Make rule set.
I don't know the answer to your questions about the use of this rule. All I can say is that this rule already existed when GNU make was first checked into source control, in Jan 1992. It's not mentioned in any ChangeLog so probably it dates back to the very earliest versions.
The actual rule is defined as a pattern rule, so changing .SUFFIXES won't help. To get rid of it you can use:
%.out : %
(no recipe) which will delete the pattern rule.
Consider the following Makefile
foo:
#echo '$#'
test:
#echo '$#'
#echo '---'
# Catch-all target
%: test
#echo '+++'
#echo '$#'
When issuing make bar the following is the console output:
$ make bar
test
---
+++
Makefile
+++
bar
I would like to understand the origin of Makefile which shows it is received as argument at some point, and also how to get rid of it in such a scheme. This is using
GNU Make 4.1
Built for x86_64-apple-darwin13.4.0
GNU make treats the makefile itself as a target that needs to be updated. See How Makefiles Are Remade:
... after reading in all makefiles, make will consider each as a goal target and attempt to update it. If a makefile has a rule which says how to update it (found either in that very makefile or in another one) or if an implicit rule applies to it (see Using Implicit Rules), it will be updated if necessary...
If you know that one or more of your makefiles cannot be remade and you want to keep make from performing an implicit rule search on them, perhaps for efficiency reasons, you can use any normal method of preventing implicit rule look-up to do so. For example, you can write an explicit rule with the makefile as the target, and an empty recipe (see Using Empty Recipes).
Hence, the catch-all-target % is used to update Makefile.
Makefiles often do not have to be updated, so it is customary to add an empty rule for that:
Makefile : ;
At the make manual said:
During the first phase it reads all the makefiles, included makefiles,
etc. and internalizes all the variables and their values, implicit and
explicit rules, and constructs a dependency graph of all the targets
and their prerequisites.
I don't understand how the dependency graph constructed? Consider the following makefile:
%.o: %.z
echo This is overriden implicit rule
default: foo.o
clean:
rm -f fmake test_second
%.o: %.c
echo This is customized implicit rule
After make command
echo This is customized implicit rule
This is customized implicit rule
is displayed, but I'm expexted that
echo This is overriden implicit rule
This is overriden implicit rule
will be, because in make rule only overrides if both the target and the prerequisite patterns match. In this case I think that %.o: %.z implicit rules matched to pattern already.
I've been doing a lot of work with Makefiles in a very, very large codebase for the last year or so. I am heartily sick of make(1s)!
The answer, in general, is "last declaration wins". You also have to contend
with the default make suffix rules (on Solaris these are found in /usr/share/lib/make/make.rules).
So if you want your overridden implicit rule to stand, place it last in the
Makefile hierarchy. If you want to flush the suffixes list, you can do either
or both of
1 add a .SUFFIXES:
line to your Makefile,
2 call make with -r
in MAKEFLAGS (env var) or on the make invocation command line.
[Also, you can prepend "#" to the start of your command to just see the output
of it, rather than the
echo [output goes here]
as well as the actual
[output goes here]
You could also gather insight by using one of the debugging options that
make(1s) allows. On Solaris, that's -d, -dd, -D or -DD. For GNU Make, it's
-d or --debug. Caution, though, dump the output from the command to a file,
because there is a lot of it.
You might want to read http://freecode.com/articles/what-is-wrong-with-make, as a piece of on-the-side illumination.