Makefile match anything rule as intermediate - makefile

Consider this simple Makefile:
%.one: %.two
echo one
%.two: %.three
echo two
%.three: %.four
echo three
all: hi.one
As expected, make all will produce:
echo three
three
echo two
two
echo one
one
But if I make an intermediate rule without any prefix/suffix:
%.one: %
echo one
%: %.three
echo one
%.three: %.four
echo one
all: hi.one
Make will fail saying there is no rule to make hi.one. Is this simply impossible with Make?

No this isn't possible, non-terminal match-anything rules are ignored for dependencies of pattern rules.
This isn't actually mentioned in the manual, but the following comment in the make source (implicit.c:321) makes it clear
/* Rules that can match any filename and are not terminal
are ignored if we're recursing, so that they cannot be
intermediate files. */

Related

GNUMake - Using text functions with match pattern as prerequisite

I want to use the match pattern of a Makefile rule in a text function in the perquisites list.
Let's say I want to build a file, and that files perquisites are any other files with the same name in a list.
list_of_files=a/x b/x a/y b/y c/z
%:
echo 0 $#
touch $#
build/%: $(filter %/$*,$(list_of_files))
echo 1 target $#
echo 1 prereq $?
touch $#
.PHONY:
all: build/x
echo
In the above case, I want for a/x and b/x rules to also be triggered as they are filtered out of the list, however they are not.
The docs are pretty clear that what you're trying won't work as-is:
It’s very important that you recognize the limited scope in which automatic variable values are available: they only have values within the recipe. In particular, you cannot use them anywhere within the target list of a rule; they have no value there and will expand to the empty string. Also, they cannot be accessed directly within the prerequisite list of a rule.
One way to deal with this (as mentioned in the above documentation) is to use the secondary expansion capability:
.SECONDEXPANSION:
getprereqs = $(filter %/$*,$(list_of_files))
build/%: $$(getprereqs)

Variable substitution in Makefile yields unexpected results

I have a Makefile:
FOO=one two
$(FOO):
echo $#
Now I run:
make one and get echo one
make two and get echo two
make three and get an error
This is expected.
However, when I change the Makefile to:
FOO=one two
$(FOO)$(FOO):
echo $#
It is still the same!
I would expect that I have to type make oneone, but this is not the case.
Why is that?
Because make trustfully pastes whatever you give it as contents. Depending on the invisible rest of the line in FOO=one two... i.e. if you have a space there or not, you are producing one twoone two or one two one two. The latter is, I think, not illegal but will produce a warning like target given more than once in same line.

How to describe multiple files in both target and prerequisites

In make, how do I use the wildcard % to describe multiple files in both target and prerequisites?
%.1: %.md
for f in $?; do ...; done
I thought the above was the way to trigger the rule to create *.1 files for any *.md that were modified since the last run, but shows this instead:
make: *** No targets. Stop.
Your rule is saying "if you need to make a .1, here is how to do so if you have a .md", you haven't asked make to do any .1. You probably need also something like:
SOURCES=$(wildcard *.md)
all: $(SOURCES:%.md=%.1)
%.1: %.md
echo $#
Note that * and % are similar (they stands for unspecified characters) but appears in different contexts (* to look for existing files, % when examining strings -- the strings are often part of file name, but that's not something mandatory and you could for instance use it to match arguments of utilities)

Rule with wildcard to depend on other rules [duplicate]

I'm observing an interesting behavior of make and I wonder if there is a reasonable explanation to it besides a bug in gmake.
Let's say we have the following in makefile:
%-animal:
echo "$* is an animal"
%-fox: %-fox-animal
%-wolf: %-wolf-animal
The difference between the last two targets is that "%-wolf" does not have any recipe, and "%-fox" has an empty recipe (i.e. just a line with a tab at the beginning).
When we try to execute the rules, here's what happens:
[root#cv19 tmp]# make freddy-animal
echo "freddy is an animal"
freddy is an animal
[root#cv19 tmp]# make freddy-wolf
make: *** No rule to make target `freddy-wolf'. Stop.
[root#cv19 tmp]# make freddy-fox
echo "freddy-fox is an animal"
freddy-fox is an animal
i.e.the pattern rule that has a recipe (although an empty one) works, the one that doesn't does not. Am I missing something in the way it's supposed to work?
Pattern rules with no recipes at all are documented as meaning something quite different from those providing a recipe, even an empty one. Instead they cancel any pre-existing implicit rule:
You can cancel a built-in implicit rule by defining a pattern rule with the same target and prerequisites, but no recipe.
Thus your "%-wolf" pattern actually serves to cancel any existing implicit rule for %-wolf-animal -> %-wolf. And there wasn't one anyway.

How to makefile parse

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.

Resources