Makefile: Pattern rule as first rule - makefile

I know that make usually executes the first target if called without any arguments. But what happens if the first target is a pattern rule? I have a Makefile here that looks as follows:
%.o: %.cc
gcc -c -o $# $<
main: main.o helper.o
gcc main.o helper.o -o $#
From my understanding of make, just calling it w/o any arguments should probably lead to some kind of error in this case because the first target, which is as far as I understood always the default target, does not make sense if make is not given any arguments. But when I call make with this Makefile, it instead builds the main target (and, of course, recursively the targets main.o and helper.o as well).
So, is it always true that make will ignore the pattern rules when looking for the first target? And is it somehow considered bad style to put those in front of the target that one really wants to be the default one? In my opinion, this is somehow confusing.

From the GNU make manual:
The order of rules is not significant, except for determining the
default goal: the target for make to consider, if you do not otherwise
specify one. The default goal is the target of the first rule in the
first makefile. If the first rule has multiple targets, only the first
target is taken as the default. There are two exceptions: a target
starting with a period is not a default unless it contains one or more
slashes, ‘/’, as well; and, a target that defines a pattern rule has
no effect on the default goal. (See Defining and Redefining Pattern
Rules.)

Related

Missing dependency in Makefile

I have these recipes in my Makefile. They generate cross-compiled objects for ARM architecture and link them into an elf binary:
%.ao: %.c
$(ARM_CC) $(ARM_CPPFLAGS) $(ARM_FLAGS) $(CFLAGS) -c -o $# $<
%.elf: %.ao startup_stm32f0xx.ao system_stm32f0xx.ao
$(ARM_CC) $(ARM_FLAGS) $other_arguments -o $# $^
This works fine from a clean build.
Contrary to my expectation, if I then say touch foo.c; make foo.elf, gmake responds with
make: 'foo.elf' is up to date.
If I try to make foo.ao, gmake says that it, too , is up to date.
What am I missing?
Edit after reading the comments:
TLDR: I did have multiple rules matching the same target, as John Bollinger alluded and HardcoreHenry said specifically.
In addition to the rules above, there's a rule for assembly sources so I can use those vendor files:
%.ao: %.s
$(ARM_CC) $(ARM_CPPFLAGS) $(ARM_FLAGS) $(CFLAGS) -c -o $# $<
I had been debugging some macros, and used -save-temps to look at preprocessor output. This option also writes .s files. So after I'd run make foo.elf, I'd have the following in my directory:
foo.c
foo.i
foo.s
foo.ao
foo.elf
I can touch foo.c, but make sees that there's a foo.s which is older than foo.ao, and produces the output that it does. On a clean build, there is no foo.s, so make finds the %.c:%.ao rule and the build proceeds from foo.c.
(BTW, .ao stands for ARM object. In addition to cross-compiling for AMR, I compile many of the sources to run unit tests on the host, using the built-in .o:.c rule)
I'm not a fan of pattern rules.
Make can make very strange decisions on which rules apply depending on whatever is lying around on your hard disks.
It's all a bit arbitrary.
Much better IMHO to tell make exactly what files you need for a target.
It's pretty easy too.
Just prefix your pattern rule with the list of targets you actually want it to apply to.
This makes it a Static Pattern Rule.
objects := main.ao tools.ao devices.ao# etc
${objects}: %.ao: %.c
$(ARM_CC) $(ARM_CPPFLAGS) $(ARM_FLAGS) $(CFLAGS) -c -o $# $<
%.elf: ${objects} startup_stm32f0xx.ao system_stm32f0xx.ao
$(ARM_CC) $(ARM_FLAGS) $other_arguments -o $# $^
As an added bonus, make now won't try to create the pre-existing startup_stm32f0xx.ao and system_stm32f0xx.ao.
Usually I find it nicer to list the source files, but YMMV:
sources := main.c tools.c devices.c
objects := $(patsubst $.c,%.ao,${sources})
(P.S. Using a Static Pattern Rule doesn't really give you any advantage over a normal rule in this noddy case. I just wanted to show a small tweak that would make your makefiles much more consistent in their behaviour.)
I know it's bad form to use an answer to respond to another answer, but I ran out of space in a comment to #bobbogo's answer.
Sorry but I can't agree with your assessment of pattern rules. It's not true that you will get "strange decisions" based on "whatever is lying around on your harddisks", and it's certainly not arbitrary.
There is one advantage of static pattern rules over pattern rules, and that is also its downside: a static pattern rule is a shorthand for creating an explicit rule, so that rule will always be used to build that target. A pattern rule, on the other hand, is just one possible way to build a target: if the prerequisites of a pattern rule don't exist and can't be made, then make keeps going and looks for other pattern rules that might be able to build that target.
So if you have multiple possible ways you can build a target then an explicit rule cannot be used for that.
The problem with pattern rules is that if NO pattern rule applies then make just assumes there is no rule to build that target. If the target exists then make simply says "up to date" (as we see in the question) since there's no rule to build it. That can be confusing to users.
If you use an explicit rule (including a static pattern rule) and some prerequisite doesn't exist and can't be created, then make will exit with an error, which can make it easier to figure out what went wrong.

Prioritizing pattern rules in Make

I have (roughly) this Makefile:
.PHONY: all
.SUFFIXES:
OUT = /www/web
all: $(OUT)/index.html
# rule 1
%.html: %.in
build_html $< $#
# rule 2
$(OUT)/%: %
cp $< $#
This Makefile has a problem, since there are two different ways to build $(OUT)/index.html:
build ./index.html (rule 1), then copy it to $(OUT) (rule 2).
copy ./index.in to $(OUT) (rule 2), then build $(OUT)/index.html (rule 1).
I want make to always prefer option 1. How can I indicate that there is a preferred order between these two pattern rules?
(I can think of a few hacky ways to accomplish it for this particular case, but I want a solution that is as general as possible---for instance, changing the pattern of rule 2 to $(OUT)/%.html: %.html will fix the problem, but loses generality since I need to repeat myself if I want to handle other kinds of files in the same way later.)
A quote from the GNU Makefile Manual:
It is possible that more than one pattern rule will meet these criteria. In that case, make will choose the rule with the shortest stem (that is, the pattern that matches most specifically). If more than one pattern rule has the shortest stem, make will choose the first one found in the makefile.
So, you can try to create rules which ensure shorter stems to take priority. Alternatively, you could use static pattern rules to limit the scope of what gets copied where, as so:
%.html: %.in
build_html $# $<
$(expected_out) : (OBJS)/% : %
cp $# $<
and then prepopulate $(expected_out) with what you want in there. Finally, you can add:
$(OUT)/index.html : index.html
somewhere in your makefile, as make prefers the 'shortest path' to building an object, which would only be one pattern rule in this case.
While #John's answer best fits my use-case (I know exactly what files belong in $(OUT)), there is also an alternative solution: mark the desired intermediate file as "precious".
.PRECIOUS: index.html
This will also instruct Make not to delete index.html, which it would otherwise do for you.
This works thanks to Make's algorithm for choosing implicit rules. Make favors rules whose dependencies exist or ought to exist, and a file "ought to exist" if it has an explicit rule or is a dependency of another rule. This applies even if it is a dependency of a special target like .SECONDARY, .INTERMEDIATE, or .PRECIOUS. For more info, also see the manual section on "Chains of Implicit Rules".

make - pattern rule target wrongly treated as intermediate

I have a makefile that does something like this:
.INTERMEDIATE: gen0.tmp gen1.tmp
.PHONY: %_test
%_test: tests/%.so
ln -fs $< test.so
tests/%.so: gen.o test_src/%.c
cc -shared $^ -o $#
gen.c: gen0.tmp gen1.tmp
cat $^ > $#
gen%.tmp:
seds and awks and non-relevant stuff
As far as i have understood make's documentation, all files created from implicit rules are treated as intermediate, but that is not true for pattern rules, yet whatever .so i create with %_test rule is being deleted with other intermediate files, unless it existed before calling make. What is wrong here?
Also
.SECONDARY: tests/%.so
Doesn't work and
.SECONDARY:
does, but then targets explicitly marked as .INTERMEDIATE aren't beeing deleted, and i don't think marking my main target as .SECONDARY is good practice.
PS: i use make version 3.81
I don't understand your statement all files created from implicit rules are treated as intermediate, but that is not true for pattern rules.
A pattern rule IS a (type of) implicit rule. It absolutely is the case that targets which are created as a result of a pattern rule may be considered intermediate.

Understanding pattern rules

I am trying to wrap my head around pattern rules and how they function. I am using this article for reference which states
A pattern rule is a concise way of specifying a rule for many files at
once. The rule will depend on the file names, but usually it depends
on them in a simple way. You specify a pattern by using the %
wildcard. When present in the dependency list, % matches any string of
any length; when present in the list of targets, % stands for the
string that % in the dependency list matched.
The following pattern rule will take any .c file and compile it into a
.o file:
%.o: %.c $(CC) $(CFLAGS) $(INCLUDES) -c $(input) -o $(output)
(This assumes that you have the variables CC, CFLAGS, and INCLUDES
defined to be something suitable. Makepp will guess a value for CC and
CFLAGS.)
The first line of the rule says that it applies to every possible
input file that matches the pattern %.c. These .c files can be
transformed into the corresponding .o file using the specified
actions.
The action of rule is quite similar to the other actions we've seen
previously, except that it uses automatic variables. An automatic
variable is a variable whose value is automatically set by makepp
depending on the rule that it appears in. Some useful automatic
variables are:
$(input)
The name of the first input file. In this rule, this would be the file that matches the %.c pattern. $(dependency) is a synonymn for $(input). In older makefiles, you will also see the cryptic symbol $< used as well.
$(output)
The name of the first output file. In this rule, this would be the file that matches the %.o pattern. $(target) and $# are synonymns.
$(inputs)
The name of all explicitly listed input files. In this case, since there is only one, $(inputs) is equivalent to $(input). $(dependencies) and $^ are synonymns.
$(outputs)
The name of all explicitly listed targets. In this case, since there is only one, $(outputs) is equivalent to $(output). $(targets) is a synonymn for $(outputs).
Here are the questions that I have:
1 ) Suppose I have 2 files FileA.c and FileB.c. When I apply the above mentioned pattern rule how would that apply to the above two files. The example given only deals with one file.
2) Whats the difference between the automatic variable input and inputs
A pattern rule will be applied to each target file that matches the rule that make needs to build.
So if you need to build both FileA.o and FileB.o (because they are both listed as prerequisites of some other target (e.g. FileBin: FileA.o FileB.o) that rule will be run twice, once for each.
Take the rule
FileBin: FileA.o FileB.o
#echo '$$input = $(input)'
#echo '$$inputs = $(inputs)'
When run that would output
$input = FileA.o
$inputs = FileA.o FileB.o
It should also be pointed out that input and output are makepp variable names and not valid for GNU make itself.

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