Static pattern rules in Makefiles - makefile

I was looking at Make documentation and I thought that the below would call first the little then the big target, but it stops after big with no attempts to proceed to little.
targets = bigoutput littleoutput
$(targets): %output : %
#echo Done
little:
#echo in little
big:
#echo in big
Here's the output:
in big
big > bigoutput
I thought that the static pattern rules were the answer to being able to process multiple targets by following unique prerequisites for each. What am I missing?
Thanks!!

Make's concept of the "default goal" is independent of everything else. No matter what you do, it always is only a single target.
To work around it, use all: $(targets) as the first line.
Static pattern rules are useful for a different purpose: when you have multiple generate files that have names that match the pattern, but need to be built using different rules.

Related

How to share the same recipe for multiple pattern rules in Make?

I have rules like this:
.SECONDEXPANSION:
foo/%.x: bar/$$*$$(suffix $$#)
{complicated recipe}
foo/%.y: bar/$$*$$(suffix $$#)
{complicated recipe}
The recipes are exactly the same, so I want to share them.
But this doesn't do the same thing, which doesn't make sense to me:
.SECONDEXPANSION:
foo/%.x foo/%.y: bar/$$*$$(suffix $$#)
{complicated recipe}
What's the correct way to share the same complicated recipe for multiple pattern rules?
Your attempt doesn't work because pattern rules with multiple targets and explicit rules with multiple targets are treated quite differently.
An explicit rule with multiple targets creates multiple explicit rules, one for each target. But a pattern rule with multiple targets creates a single rule that builds multiple targets as its output. So your rule here:
foo/%.x foo/%.y: bar/$$*$$(suffix $$#)
{complicated recipe}
actually tells make that a single invocation of {complicated recipe} will create both foo/%.x and foo/%.y targets.
I'm not sure what you mean by I can't do it in one line either but you can always use a macro. If you need multiple logical lines use the define syntax:
define complex_recipe
....
endef
In your comments you write the $$ duplication really makes the rules unwieldy but the only reason you need that is because you're trying to define multiple pattern rules in one stanza. If you write it multiple times you don't need any of that stuff:
define complex_recipe
...
endef
foo/%.x : bar/%.x ; $(complex_recipe)
foo/%.y : bar/%.y ; $(complex_recipe)
Speaking personally this would be my preference to how to write it rather than creating an external script or something like that.

make file, what is the idea behind coining of special variables as described below

In make file, for one example, $# is the name of the file being generated,
Find it difficult to remember these special variables
Is there a systematic way that this been coined?
or How this can be remembered?
No, there is no mnemonic that I can think of. The list of automatic variables is documented here. There are really only three that are typically used, so they're not that hard to remember once you get used to them: $# for the target, $< for the first prerequisite, and $^ for all the prerequisites. The others are more for special situations.
What you really need is a cheat-sheet. There are plenty available (search for makefile cheat sheet , and maybe specify the variant, eg gnu).
As an example: http://www.cheatography.com/bavo-van-achte/cheat-sheets/gnumake/

Makefile generator creates two files

I have a generator program that creates two version files, say ver.h and ver.cpp. My ultimate build target depends on both of these files, and the rule for building both is that one program. If I did this:
build : ver.h ver.cpp
ver.h ver.cpp :
./gen/version/program
then a parallel build could run program twice, which, while not bad is just excessive. I figure I could have them both depend on a phony target:
ver.h ver.cpp : do-version-impl
do-version-impl:
./gen/version/program
.PHONY : do-version-impl
Is that the best way to do this? It smells a little funny to have to introduce a phony rule to do this.
Using the phony target as the prerequisite is a bad idea. program will be run even if ver.* files exist, which is a false positive error.
More subtly, GNU Make is only guaranteed to update its file timestamp, if that file is a target of a rule with a recipe. So here, even though program is always run, anything that in turn depends on ver.* files might not get updated at all!
In my opinion it is best to not make up unnatural patterns for each target, but instead, go explicit:
There is a "main" file that you are generating, that is ver.cpp. Use the "no-op" recipe ; for the other one, which can be put on the same line like this:
ver.h: ver.cpp ;
ver.cpp: Makefile
./gen/version/program
This method starts with what you wrote, but adds the very important ;.
If you did not have a natural candidate for the "main" file, then in my opinion it is best to use a "sentinel":
ver.h ver.cpp: sentinel ;
sentinel: Makefile
./gen/version/program
touch $#
Again, this method is similar to one of your methods, but very importantly, does not use a phony, but a real file.
See 10.5.1 Introduction to Pattern Rules specifically the last paragraph:
10.5.1 Introduction to Pattern Rules
...
A pattern rule need not have any prerequisites that contain ‘%’, or in fact any prerequisites at all. Such a rule is effectively a general wildcard. It provides a way to make any file that matches the target pattern. See Last Resort.
...
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.
So you could use something like this:
v%r.h v%r.cpp:
./gen/version/program
I believe you need that odd patterning to have make consider the pattern to match (I don't believe it will match % against an empty string as ver%.h ver%.cpp would need). (I can't find reference to this in the manual at the moment though.)

Why .PHONY:target and not target:.PHONY?

I still don't understand why "phony" rules in Makefiles have ".PHONY" as their target. It would be much more logical as a prerequisite.
Do I have to elaborate on this? If A depends on B and B is phony, then A is phony too. So the dependency graph .PHONY←B→A is waay surprising compared to .PHONY→B→A. (Another argument is that an implementation of make must handle the .PHONY target very special.)
While this critique may seem rather theoretical (to pointless) - "since make is so ancient, its syntax is here to stay". But I am not proposing any syntax change, there is an alternative:
With GNU Make (at least), the following Makefile declares a phony target_A:
target_A: _PHONY
touch target_A
_PHONY:
#noop
Question 1: This is so simple and clean, surely I am not its first inventor. In fact, given this alternative, why did make ever need the special syntax?
It seems to me that this would also quite nicely solve questions about wildcards in phony targets, and could even shed some light on .PHONY's meaning when beginners doubt.
Question 2: Can you think of any circumstance where this approach is inferior? (Is invoking make .PHONY of any use?)
(I should mention that while I have invoked other makes, GNU Make is the only implementation that I have some experience with - reading and writing Makefiles.)
One big problem with using target_A: .PHONY is that it makes it much harder to use many of make's built-in variables. Take this common recipe as an example:
%.a: $(OBJ_FILES)
$(LD) $(LFLAGS) -o $# $^
The $^ variable pulls in everything that's listed as a prerequisite. If .PHONY was also listed there then it would be passed to the linker on the command-line, which would probably not result in anything good happening. Using meta-targets like .PHONY as prerequisites makes these built-in variables significantly less useful, as they require a lot of extra processing like $(filter-out .PHONY,$^) every time they are used. Inverting the relationship and instead making .PHONY the target is a bit awkward for the sake of thinking about dependency trees, but it cleans up the rest of the makefile.

Can I have more than one % sign in a makefile target?

So I have a makefile with a target dependency like this:
all: $(foreach lang, $(LANGS), $(foreach models,$(MODELS),targetName$(model).xml$(lang)))
and the targetName target looks like this:
targetName%.xml%: MODEL\=% targetName.xml*
But it doesn't work. I get this error:
make[1]: *** No rule to make target `targetNameMYMODEL.xmlen', needed by `all'. Stop.
however, calling 'all' with a hardcoded language in the targetName target like this works:
all: $(foreach lang, $(LANGS), $(foreach models,$(MODELS),targetName$(model).xmlen))
and calling 'all' without the language in either all or targetName works fine as well. I'm thinking perhaps Makefile doesn't like having two percent signs in the target name.
Also, since I sort of inherited this makefile, can someone tell me what that MODEL\=% means? There is another target that looks like this: MODEL%: ; but i'm not sure what the \=% means.
Edit:
So to clarify further based on this reponse:
I have a list of, say, 5 Models and a list of say 5 Languages, the goal is to generate 25 files, one for each combination of languages and models.
targetName%.xml target would originally build a file called targetName.xml but now I need it to build something like targetName.xml That's why I needed the two % signs.
I'm cycling through these two lists with a nested foreach as shown above, but I'm having a hard time passing those variables around to targets. I've tried exporting the language variable from the foreach statement, I've tried putting the contents of the targetName%.xml in a for loop to loop through the languages there. The latter doesn't work because there are Makefile commands (like eval for example) in the 'do' portion of the loop.
You're right, Make doesn't like two % symbols in the target name. That's just one of the ways in which Make's wildcard handling isn't all one might wish for. There is a way to generate all of the pattern rules iterating over the values of one variable (and using % for the other) automatically; it's a little ugly, but if that's what you want we can show you.
But this line is a mess:
targetName%.xml%: MODEL\=% targetName.xml*
Apart from the problem of two wildcards in the target, the last preq, targetName.xml* will mean exactly that: a target (or file) called targetName.xml*. The asterisk will not be expanded, not to a list of all existing files that start with targetName.xml, or anything else.
Then there's MODEL\=%, which indicates that the author of this makefile was a little confused (and didn't believe in testing). If the value of the wildcard is foo, then this will indicate a prerequisite which is a target (or file) named MODEL=foo. The \ "escapes" the =, so that Make will not abort, but that is simply suppression of a healthy error message. I think what the author had in mind was something like this:
targetName%.xml: MODEL=%
targetName%.xml: $(wildcard targetName.xml*)
do some things
The first rule is not specifying a prerequisite, it is setting a target-specific variable. So when Make tries to build targetNamefoo.xml by doing some things, the variable MODEL will have the value foo in the context of that command. The second rule has a preq list, generated by wildcard; you can't mix target-specific variables and preqs in one line.
We can give further advice, but it would help if we could see a little more clearly what you're trying to do.
Worth noting the official documentation on the matter:
10.5 Defining and Redefining Pattern Rules
You define an implicit rule by writing a pattern rule. A pattern rule looks like an ordinary rule, except that its target contains the character % (exactly one of them). The target is considered a pattern for matching file names; the % can match any nonempty substring, while other characters match only themselves. The prerequisites likewise use % to show how their names relate to the target name.
Thus, a pattern rule %.o : %.c says how to make any file stem.o from another file stem.c.
Note that expansion using % in pattern rules occurs after any variable or function expansions, which take place when the makefile is read. See How to Use Variables, and Functions for Transforming Text.
Source: https://www.gnu.org/software/make/manual/html_node/Pattern-Rules.html

Resources