Create pattern rule for patterns in a variable? - makefile

I have this simple pattern rule
%.o : %.cpp
recipe
I'd like to use this rule but with the added constraint that the pattern matches one of the words in a variable called FILENAMES.
Is there a way I can do this?

This is known as Static Pattern Rules.
With that syntax you provide list of possible targets, but use pattern for generate own rule for every target in this list:
FILENAMES = foo bar
# Generate list of precise targets names
FILENAMES_OBJ = $(addsuffix .o, $(FILENAMES))
$(FILENAMES_OBJ): %.o: %.cpp
<recipe>

Related

Makefile: Pattern rule that can ignore directories

I am trying to have a Makefile rule that can generate an object file from a source file in a directory that is specified explicitly.
exe: foo.o bar.o
foo.o: path/to/foo.c
%.o: %.c
echo Making $# from $<
This example will find it needs to make "exe", then search to make "foo.o". The "foo.o" search will try pattern rules with stem "foo" and fail to use the rule because "foo.c" doesn't exist. I want to find a way to have it see that "foo.o" can be compiled from "path/to/foo.c" using the pattern rule.
In my case it doesn't make sense for me to have the rule be "%.o: path/to/%.c" because the path should be specified for each target that needs the source to be located in another directory.
The pattern rule works for "bar.o" being made from "bar.c" within the same directory and I want to keep that working.
The solution I am going with for now is:
define c-to-o-command
echo Making $# from $<
endef
exe: foo.o bar.o
foo.o: path/to/foo.c
$(c-to-o-command)
%.o: %.c
$(c-to-o-command)
This has a drawback that the command for the pattern rule is not visible in the Makefile at the same place. It also will need to be expanded for other pattern rules that may need to have this "out of path" dependency.

GNU Make pattern rule depending on non-pattern file

In GNU Make, what exactly are the semantics of a pattern rule that depends on a non-pattern file?
I have the following snippet in a Makefile. When foo.a exists, GNU Make doesn't seem to create foo.b when make foo.b is called.
.SUFFIXES:
%.b: move_a_to_b.artifact
move_a_to_b.artifact:
mv foo.a foo.b
touch move_a_to_b.artifact
The following, however, works fine and moves the file from foo.a to foo.b.
.SUFFXIES:
%.b: %.a
mv $< $#
As does this, with a pattern rule depending on a pattern rule
.SUFFIXES:
%.b: %.intermediate
mv $< $#
%.intermediate: %.a
mv $< $#
It doesn't have anything to do with pattern rules depending on non-patterns. That's fine and it has the expected semantics: for any file ending in .b if it's out of date with respect to the file move_a_to_b.artifact then the recipe will be run.
Your issue is that you're not defining a pattern rule, you're deleting a pattern rule. A pattern rule must always have a recipe. A pattern rule without a recipe deletes the pattern rule. See Canceling Pattern Rules.
You have to add a recipe, then it will do something:
%.b : move_a_to_b.artifact
#echo do something to create $#

Why GNU Make's secondary expansion does not work with pattern rules for dependencies?

Consider this makefile:
%: %.c
#echo making $#
#touch $#
.SECONDEXPANSION:
%.pid: $$(basename $$#)
$(<D)/$(<F) --pidfile=$<.pid
Here, the first rule builds a program and second rule starts it, producing a pid-file. Note: I know that secondary expansion is unnecessary in this example; the real makefile is more complex and I really need secondary expansion there.
So, typing make foo.pid, I expect Make to build foo from foo.c by the first rule and then run ./foo --pidfile=foo.pid by the second one.
However, it does not seem to work:
$ make -f Makefile.test foo.pid
make: *** No rule to make target 'foo.pid'. Stop.
This somehow relates to secondary-expanded dependencies which are provided by pattern rules. If I write either
%.pid: % in the second rule (i. e. get rid of secondary-expansion), or
foo: %: %.c in the first rule (i. e. write an explicit static pattern rule),
it all suddenly works. Why? Is this a limitation of GNU Make? In my case, I'd like to avoid pre-listing all possible programs in the first rule.
I think your situation is described in section 10.5.5 Match-Anything Pattern Rules. Whay you have here is a non-terminal match-anything rule, which is not allowed to match a file name that indicates a specific type of data.
If you had let's say
%:: %.c
#echo making $#
#touch $#
it would work.

GNU Makefile - Pattern rule with multiple targets with one dependency ignores all targets but the first

I want to make a language depend target. In Particular: I have one source-file and I want to create different Objects which where add to the corresponding language folder. That single source file will differ in the C-Flags, the compiler will get. As long as I used it in a static way, it works quite fine.
de/info.o en/info.o es/info.o : info.c
$(ECHO) (DEP) $< for $#
Now I thought, it would be great if it is a bit more dynamic, in case i'll add a new language depending file. So I used a wildcard as followed:
de/%.o en/%.o es/%.o : %.c
$(ECHO) (DEP) $< for $#
But now it just make the first target and ignores the rest. The Make-Debug prints the following thing:
Successfully remade target file `de/info.o'.
Considering target file `en/info.o'.
File `en/info.o' was considered already.
Just in case: No, the objects do not exist. So there is no target, but an existing dependencie, so make should execute the rules.
EDIT: Found a solution for that Problem.
define FOO
$(1)/%.o : %.c
$(ECHO) $$< for $(1)
endef
$(foreach lang,$(LANGUAGE_LIST), $(eval $(call FOO,$(lang))))
Inspired by: http://www.gnu.org/software/make/manual/make.html#Eval-Function
Pattern rules work differently than implicit rules. While an implicit rule such as
a b c: d
command
is equivalent to the longer notation
a: d
command
b: d
command
c: d
command
this does NOT hold for pattern rules. Pattern rules with multiple targets are explicitly required to build all of their targets in a single invocation of command. Thus you would have to write
$ cat GNUmakefile
all: de/x.o en/x.o es/x.o
de/%.o: %.c
#echo $# from $<
en/%.o: %.c
#echo $# from $<
es/%.o: %.c
#echo $# from $<
$ gmake
de/x.o from x.c
en/x.o from x.c
es/x.o from x.c
The relevant documentation is found in 10.5.1 Introduction to Pattern Rules of the GNU 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.

Makefile pattern matching

There are two pattern rules in my Makefile. target1 actually matches both these two rules. When I run the makefile, it always try to run the recipes of pattern rule1 instead of pattern rule2 I desire. For a specific target(target1 for example), is it possible to have makefile process skip matching rule1 and go ahead to find the second match(rule2)???
## pattern rule 1
%.xml: $^
recipes ....
## pattern rule 2
/opt/test1/xml/default%.xml: $^
recipes ....
## target1
/opt/test1/xml/default1.xml: prereq

Resources