What is a semicolon in a makefile prerequisites list? - makefile

In one of the early sections of the GNU make manual, Section 3.7, there is an outline of a makefile recipe
immediate : immediate ; deferred
deferred
involving a semicolon in the prerequisites list. So a valid recipe could be
output.o : output.c header1.h header2.h; header3.h
gcc output.c -o output.o
What is the point of the semicolon? Since the aforementioned section talks about immediate and deferred variable expansion, I am guessing that the part up to the semicolon is expanded immediately and the part of the semicolon is expanded only once the target is executed. Can anybody confirm?
I have found similar questions on SO but those present special cases and none of the their accepted answers seem to get the point.

As explained in 4.2 Rule Syntax:
In general, a rule looks like this:
targets : prerequisites
recipe
…
or like this:
targets : prerequisites ; recipe
recipe
…
[...]
The recipe lines start with a tab character (or the first character in the value of the .RECIPEPREFIX variable; see Special Variables). The first recipe line may appear on the line after the prerequisites, with a tab character, or may appear on the same line, with a semicolon. Either way, the effect is the same.
(Emphasis mine.)
Your example is equivalent to
output.o : output.c header1.h header2.h
header3.h
gcc output.c -o output.o

Semicolon simply allows to write the first line of the recipe on the same line as the prerequisites list.
This way (given that your recipes fit a single line) you can write a Makefile w/o any evil tabs. There's no much use in it otherwise.

Related

How to include flags for valgrind in a makefile?

I have a makefile with a valgrind target that looks like this:
# expects a file `test.keys` to exist; it can contain any numbers.
valgrind: $(PROG) test.keys
valgrind ./$(PROG) < test.keys
If I wanted to include valgrind flags such as --leak-check=full --show-leak-kinds=all, where would I put them? Do I put them right after valgrind:, or only on the second line before ./$(PROG) but after valgrind?
Thanks in advance!
The name "valgrind" appears twice in your rule because you are using it to mean two different things: it is the name of the analysis tool that you want to execute, and it is the name of your makefile rule, which is arbitrary. You could just as well have named your rule "pumpernickel":
pumpernickel: $(PROG) test.keys
valgrind ./$(PROG) < test.keys
The flags are to be passed to valgrind (the analysis tool) as if you were invoking it on the command line. That's what the second line is; that line is passed to the shell as a command. So that's where the flags belong.
P.S. Whatever name you choose for this rule, be aware that by default Make expects a rule with a given name to build a file with that name. This rule builds nothing, so you should use .PHONY to warn Make not to expect this rule to behave in the default way.

Makefile: Pattern rule as first rule

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.)

What does it mean when a semicolon occurs in a makefile target's prerequisites?

I've run into this syntax in a Makefile that I'm modifying:
some_target: ;
another_target: ...
What does the semicolon mean in this context?
This is an empty recipe, which is used if you want to prevent the target from being assigned implicit recipes.

How to call functions within order-only prerequisites?

Given this bit of Makefile:
# for pattern matching
$(OBJDIR) := build
# just to see if a level of indirection will work
my_dir = $(dir $(1))
$(OBJECTS) : $(OBJDIR)/% : $(HEADERS) $(SRCDIR)/% | % $(dir %) $(call my_dir,%)
#echo output-only = $|
This is a static pattern rule with order-only prerequisites.
Consider the target "build/utility/debug.js". The output of the above rule will be this:
output-only = utility/debug.js ./
The first component, "utility/debug.js", is properly copied from the stem (%).
The second component, "./", is the output of calling the dir function in the prerequisites list.
The third component, an empty string, is the output of calling my my_dir function in the prerequisites list.
If I change my_dir to this:
my_dir = $(1)
The output remains the same. If I change it to this:
my_dir = "foo"
Then make complains there is no rule to make "foo" (which is expected). It appears, then, that $(1) is not getting bound in the call to my_dir.
What's going on? Why can't I pass the stem to a function? I have a workaround that uses secondary expansion, but I want to know why I can't write my rule this way.
EDIT: I'm new to stackoverflow, forgive me if this is not the way things are done here.
I want $(1) because I am passing the stem as an argument to my_dir, as Alex pointed out.
I don't know why it was suggested I want "$". I don't believe $ by itself expands to anything in any context.
I know that automatic variables are only available in the recipe. I am not using an automatic variable in the prerequisites - I am using the stem:
Each target is matched against the target-pattern to extract a part of the target name, called the stem. This stem is substituted into each of the prereq-patterns to make the prerequisite names (one from each prereq-pattern). - the manual
The fact that the stem is available is demonstrated by the example: the stem expands to the correct value when used alone, but not when passed to a function.
As can be seen in this section of the GNU make manual, variable and function references in the list of prerequisites are immediately expanded, during the read in phase. This means, before any pattern matching is done, so the % has no special meaning yet; it is interpreted as a literal character in the two function references, $(dir %) and $(call my_dir,%), both having ./ as a result, which get merged in the reference to $| in the recipe.
I don't know of any other workaround than the one you already found, i.e. secondary expansion.
Note $1 is not a special variable that expands to anything interesting related to pattern rules (or static pattern rules). The $1 variable only has unique behavior within the context of a user-defined macro invoked by the $(call ...) function.
You wanted to use $*, not $1; $* is an automatic variable which expands to the stem of the target of the rule.
However, in all versions of make (including the POSIX standard definition of make), automatic variables (including $*, $<, $#, $^, etc.) are only available in the context of the recipe. They are not available in the context of the target or prerequisite lists. See the GNU make manual section on Automatic Variables for more details.
As you suggest, there is a GNU make-specific feature enabled by the .SECONDEXPANSION pseudo target which provides a way to avoid this limitation.

$+ meaning in makefile

What does $+ in a GNU makefile mean?
Also, please give me some good lookup manual for writing makefiles.
From the make manual:
$^ The names of all the prerequisites, with spaces between them. For prerequisites which are archive members, only the member named is used (see Archives). A target has only one prerequisite on each other file it depends on, no matter how many times each file is listed as a prerequisite. So if you list a prerequisite more than once for a target, the value of $^ contains just one copy of the name. This list does not contain any of the order-only
prerequisites; for those see the `$|' variable, below.
$+ This is like `$^', but prerequisites listed more than once are duplicated in the order they were listed in the makefile. This is primarily useful for use in linking commands where it is meaningful to repeat library file names in a particular order.
In both cases, all I can say is RTFM... or RTFI in this case. Type
info make
at a command prompt and all the information you could ever want will be at your fingertips.
For $+ specifically: it refers to the names of all the prerequisites of the current rule. See for example http://uw714doc.sco.com/cgi-bin/info2html?(make.info)Automatic&lang=en

Resources