$+ meaning in makefile - 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

Related

Automake: Why is my Makefile picking files from the source directory instead of the build directory?

I'm using Automake.
I have a few source files listed in dist_man1_MANS like this:
dist_man1_MANS = some-file.1 some-other-file.1
Now, Automake + configure eventually generate this in Makefile:
dist_man1_MANS = some-file.1 some-other-file.1
# ...
install-man1: $(dist_man1_MANS)
# generated recipe here
Since I'm not prefixing the .1 files with $(srcdir), I assume that, since I run make from the build directory (its current working directory), it should find them in the build directory.
So, I'm doing an out-of-tree build, for example, in /tmp/build:
/path/to/src/configure --prefix=$(pwd)/install
make
make install
and the build succeeds, that is, make finds the man pages and installs them. They are not in the build directory, however. I add this to the generated Makefile:
install-man1: $(dist_man1_MANS)
#echo ">>> $(^)"
#echo "::: $(dist_man1_MANS)"
# generated recipe here
Now, I would assume that both echos print the same thing, because $^ means the names of all the prerequisites, with spaces between them. To my surprise, the output is:
>>> /path/to/src/some-file.1 /path/to/src/some-other-file.1
::: some-file.1 some-other-file.1
So:
How did make find the /path/to/src/ prefix exactly? Where does it come from in this very context?
Why do $^ and $(dist_man1_MANS) differ?
I found the answer.
Automake sets the VPATH variable in its generated Makefile, a special variable for make, to something like:
VPATH = /path/to/src
From the previous links:
4.5.1 VPATH: Search Path for All Prerequisites
The value of the make variable VPATH specifies a list of directories that make should search. Most often, the directories are expected to contain prerequisite files that are not in the current directory; however, make uses VPATH as a search list for both prerequisites and targets of rules.
So make searches for the some-file.1 and some-other-file.1 prerequisites in the current working directory first, then for /path/to/src/some-file.1 and /path/to/src/some-other-file.1 if it cannot find the first ones. In this case I understand why $^ is different from $(dist_man1_MANS): $^ is the list of effective (resolved) prerequisites.

searchpath for prereqisites, like vpath, but only for some pattern rules

I'm trying to build several executables in one make instance, as suggested by
Recursive Make Considered Harmful.
The arguments of that paper apply to my project because some of my source files are generated, and go into multiple executables.
The object files for each of these executables go into separate directories, because they are compiled with different preprocessor flags.
How can I specify separate vpath settings for each of these executables, so that source files with duplicate filenames in separate directories go into the executables where I want them to go?
Setting vpath before the rules to build the object files for one executable, and erasing it afterwards (by not giving any directories) doesn't have the desired effect. Apparently, the last setting is used for all the rules.
Solutions I see currently:
Rename source filenames to use unique names so that I can use a global vpath setting
Instead of vpath, use separate rules for each source directory, with the source directory in the prerequisite pattern (*)
Recursive make, with separate vpath settings in each make instance, and somehow deal with the resulting trouble.
Use something different than make.
Is there a better solution, or which one of the above would you prefer?
(*) The solution with separate rules looks like this:
build/$(PROGRAM)/%.o: %.c
$(COMPILE_RECIPE)
build/$(PROGRAM)/%.o: $($(PROGRAM)_SOURCE_DIR)/%.c
$(COMPILE_RECIPE)
Ok for my current project, but would become ugly fast, if there where more than one directory different in the source paths of the executables
Edit: Test for suggestion of #Etan, which shows that $^ is empty, when the prerequisites appear only in pattern rules (y/y.c) - this only works if each dependency is given directly, as for x/x.c.
.PHONY: all
all: build/x.o build/y.o
build/x.o: x/x.c
# the following rule is ignored:
build/%.o: y/%.c
# because there is a matching pattern rule with a recipe:
build/%.o:
#echo \"$#\" from \"$^\"
#touch $#
The files x/x.c, y/y.c and the directory build exist.
output:
"build/x.o" from "x/x.c"
"build/y.o" from ""
Tested with GNU Make 3.82.90
First, it's never correct to use VPATH or vpath to find derived files (files that are built by make)... that includes "source files that are generated" (if they are generated by make, and not before make is invoked somehow). VPATH/vpath can only be used to find source files (files that are not built by make). See How not to use VPATH for more information.
Second, vpath is a global setting, not a per-target setting. Whenever make wants to find a prerequisite and that prerequisite doesn't exist "normally", make will use the vpath settings to find it. There's no facility in vpath to say "for this target use these vpath settings, for that target use those". In an ideal world, you would be able to set VPATH as a target-specific variable but this doesn't work.
There are various ways to generate prerequisites based on a target: you might find some of the suggestions on metaprogramming in make helpful.
Lastly, the makefile example you give regarding $^ is not correct:
# the following rule is ignored:
build/%.o: y/%.c
# because there is a matching pattern rule with a recipe:
build/%.o:
#echo \"$#\" from \"$^\"
#touch $#
You cannot specify a pattern rule without any recipe and have it "add" prerequisite patterns to some other existing pattern rule. It works for explicit rules, to add more prerequisites to a target, but specifying a pattern rule with no recipe simply deletes the pattern rule.
So, $^ is empty for build/y.o because there are no prerequisites defined in the pattern rule and you've not defined any explicit prerequisites for build/y.o like you did for build/x.o.
ETA: The reference to metaprogramming was to suggest that you can use it to make your second option, which is the one I would use, be less typing and easier maintenance. Pick the method you prefer and auto-generate the various pattern rules. This might be termed a "fifth option".
Other than that any of the four you suggest are fine, and there isn't another option you're missing that I'm aware of.

Extracting part of a match in a makefile rule

I have a makefile which generates a bunch of versions of an image in different places:
website/img/logo_256.png
website/img/logo_152.png
/tmp/logo_64.png
and so on (the /tmp/ generation is so I can later use those files to later generate a multiresolution .ico, the details of that aren't important).
I'd like a rule of the form
logo_%.png: ${SRC}
convert $^ -thumbnail $*x$* $#
but, $* brings in the matched directory too, so I get a command of the form:
convert logo_1024.png -thumbnail /tmp/64x/tmp/64 /tmp/logo_64.png
which is incorrect (I need 48x48, not /tmp/48x/tmp/48).
Or I can write
/tmp/logo_%.png: ${SRC}
convert $^ -thumbnail $*x$* $#
website/img/logo_%.png: ${SRC}
convert $^ -thumbnail $*x$* $#
which seems ugly.
I'm sure there are ways to break down and pattern match $# to get what I want, but I'm not a makefile guru, so this would take some research.
What's the easiest way to do this?
See the second half of the Automatic Variables in the GNU Make Manual:
Of the variables listed above, four have values that are single file names, and three have values that are lists of file names. These seven have variants that get just the file's directory name or just the file name within the directory. The variant variables' names are formed by appending ‘D’ or ‘F’, respectively. These variants are semi-obsolete in GNU make since the functions dir and notdir can be used to get a similar effect (see Functions for File Names). Note, however, that the ‘D’ variants all omit the trailing slash which always appears in the output of the dir function. Here is a table of the variants:
‘$(#D)’
The directory part of the file name of the target, with the trailing slash removed. If the value of ‘$#’ is dir/foo.o then ‘$(#D)’ is dir. This value is . if ‘$#’ does not contain a slash.
‘$(#F)’
The file-within-directory part of the file name of the target. If the value of ‘$#’ is dir/foo.o then ‘$(#F)’ is foo.o. ‘$(#F)’ is equivalent to ‘$(notdir $#)’.
‘$(*D)’
‘$(*F)’
The directory part and the file-within-directory part of the stem; dir and foo in this example.
‘$(%D)’
‘$(%F)’
The directory part and the file-within-directory part of the target archive member name. This makes sense only for archive member targets of the form archive(member) and is useful only when member may contain a directory name. (See Archive Members as Targets.)
‘$(<D)’
‘$(<F)’
The directory part and the file-within-directory part of the first prerequisite.
‘$(^D)’
‘$(^F)’
Lists of the directory parts and the file-within-directory parts of all prerequisites.
‘$(+D)’
‘$(+F)’
Lists of the directory parts and the file-within-directory parts of all prerequisites, including multiple instances of duplicated prerequisites.
‘$(?D)’
‘$(?F)’
Lists of the directory parts and the file-within-directory parts of all prerequisites that are newer than the target.
Edit:
As prompted by #Ian's comment I looked again and realized that this was not a complete solution. A complete solution follows.
The above F modifiers (and the $(notdir) function) will strip the path from the target filename. That's part of what is necessary.
Additional manipulation is required to extract only the numerical component from target like /some/path/logo_64.png.
The $(basename) function will strip off suffixes (as will $(patsubst %.png,%,$#) or $(#:%.png=) in a more specific fashion).
Combining those we get from /some/path/logo_64.png to logo_64. Handling things at this point depends heavily on what the data is going to look like and what assertions about it can be made. If logo_ is a static prefix then a simple $(patsubst logo_%,%,...) will work (as will the matching substitution reference like before).
If that is not guaranteed but the guarantee can be made that the dimension will be the last underscore separated component then $(lastword $(subst _, ,...)) can be used.
The rule needed is:
logo_%.png: ${SRC}
convert $^ -thumbnail $(*F)x$(*F) $#
The $(*F), is documented very briefly in the Make manual, as quoted in Etan's answer.
‘$(*F)’ The file-within-directory part of the stem; foo in this example.
The 'stem' ($*) is anything not explicit in the pattern. That includes the wildcard, and any implicit directories. So hence in the question it had the value /tmp/48, /tmp/ from the implicit directory, and 48 from the wildcard in the pattern. So of this combined stem, I need to select just the filename part, $(*F).
Alternatively, noting that the manual states:
These variants are semi-obsolete in GNU make since the functions dir and notdir can be used to get a similar effect
we can instead do:
logo_%.png: ${SRC}
convert $^ -thumbnail $(notdir $*)x$(notdir $*) $#
In a comment, Etan also linked to the How Patterns Match section of the manual, to help understand how the stem is constructed. I found this useful and wanted to bubble it up into an answer.

How such makefile works? (is it normal?)

I encountered such pattern in makefile
CXXOBJ = f1.o f2.o f3.o
$(CXXOBJ): %.o: %.cpp
g++ -c $< -o $#
f1.o: f1.cpp f1.hpp f2.hpp
f2.o: f2.cpp f2.hpp f3.hpp macros.h
f3.o: f3.cpp f3.hpp
It works (at least with GNU make 4.0).
It uses generic recipe from 4th line,
but in addition uses dependencies defined at the bottom.
Questions
Is it standard make behavior? (or is it specific to GNU-make?)
Is it standard way to write make file? (i.e. are people usualy doing it this way or is it something 'exotic'?)
How exactly does it work?
How does make combine 2 distinct rules for same file? (just append dependency list or something more?)
(I was browsing through GNU-make manual, but could not find relevant part)
This is called static pattern rules (https://www.gnu.org/software/make/manual/html_node/Static-Usage.html). It is specific to GNU make. It might be useful when different targets require different recipes to build, but match the same pattern.
As for third question, there are no distinct rules for the same file. Everything is quite well defined, each target have corresponding .cpp file.
GNU Make manual:
One file can be the target of several rules. All the dependencies
mentioned in all the rules are merged into one list of dependencies
for the target....
There can only be one set of commands to be executed for a file. If
more than one rule gives commands for the same file, make uses the
last set given and prints an error message...

what does $< and $# mean in make file

I found these pseudo variable name in my makefile in WDK build environment. What is referenced by these variables? It is a little hard for me to get the answer by search engine because they are special, I believe.
These are automatic variables:
$#
The file name of the target of the rule. If the target is an archive member, then ‘$#’ is the name of the archive file. In a pattern rule that has multiple targets (see Introduction to Pattern Rules), ‘$#’ is the name of whichever target caused the rule's recipe to be run.
$<
The name of the first prerequisite. If the target got its recipe from an implicit rule, this will be the first prerequisite added by the implicit rule (see Implicit Rules).
They are used to build rules that can be applied to different targets so that one does not need to repeat the same rule for each and every file that must be worked on...
PS: To find the answer, I first looked for the 'all documentation on a single page' for GNU make, then used my browser's search function...

Resources