Chapter 4: Writing Rules
21
4 Writing Rules
Arule appears in the makefile and says when and how to remake certain files, called the
rule’s targets (most often only one per rule). It lists the other files that are the prerequisites
of the target, and the recipe to use to create or update the target.
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
adefault unless it contains one or more slashes, ‘/’, as well; and, a target that defines a
pattern rule has no effect on the default goal. (SeeSection10.5[DefiningandRedefining
Pattern Rules], page 118.)
Therefore, we usually write the makefile so that the first rule is the one for compiling
the entire program or all the programs described by the makefile (often with a target called
‘all’). SeeSection9.2[ArgumentstoSpecifytheGoals],page99.
4.1 Rule Syntax
In general, a rule looks like this:
targets : prerequisites
recipe
...
or like this:
targets : prerequisites ; recipe
recipe
...
The targets are file names, separated by spaces. Wildcard characters may be used (see
Section 4.3 [Using Wildcard Characters in File Names], page 23)andanameoftheform
a(m) represents member m in archive file a (seeSection11.1[ArchiveMembersasTargets],
page 129). Usuallythereisonlyonetargetperrule,butoccasionallythereisareasonto
have more (seeSection4.9[MultipleTargetsinaRule],page34).
The recipe lines start with a tab character (or the first character in the value of the
.RECIPEPREFIX variable; seeSection6.14[SpecialVariables],page73). 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. There are other differences
in the syntax of recipes. SeeChapter5[WritingRecipesinRules],page41.
Because dollar signs are used to start make variable references, if you really want a dollar
sign in a target or prerequisite you must write two of them, ‘$$’ (seeChapter6[HowtoUse
Variables], page 59). Ifyouhaveenabledsecondaryexpansion(see Section 3.8 [Secondary
Expansion], page 18)andyouwantaliteraldollarsignintheprerequisites list,youmust
actually write four dollar signs (‘$$$$’).
You may split a long line by inserting a backslash followed by a newline, but this is not
required, as make places no limit on the length of a line in a makefile.
Arule tells make two things: when the targets are out of date, and how to update them
when necessary.
To html - Library SDK class:C# PDF Convert to HTML SDK: Convert PDF to html files in C#.net, ASP.NET MVC, WinForms, WPF application
How to Convert PDF to HTML Webpage with C# PDF Conversion SDK
www.rasteredge.com
To html - Library SDK class:VB.NET PDF Convert to HTML SDK: Convert PDF to html files in vb.net, ASP.NET MVC, WinForms, WPF application
PDF to HTML Webpage Converter SDK for VB.NET PDF to HTML Conversion
www.rasteredge.com
22
GNU make
The criterion for being out of date is specified in terms of the prerequisites, which
consist of file names separated by spaces. (Wildcards and archive members (seeChapter11
[Archives], page 129)areallowedheretoo.) Atargetisoutofdateifitdoesnotexistorifit
is older than any of the prerequisites (by comparison of last-modificationtimes). The idea is
that the contents of the target file are computed based on information in the prerequisites,
so if any of the prerequisites changes, the contents of the existing target file are no longer
necessarily valid.
How to update is specified by a recipe. This is one or more lines to be executed by
the shell (normally ‘sh’), but with some extra features (seeChapter5[WritingRecipesin
Rules], page 41).
4.2 Types of Prerequisites
There are actually two different types of prerequisites understood by GNU make: normal
prerequisites such as described in the previous section, and order-only prerequisites. A
normal prerequisite makes two statements: first, it imposes an order in which recipes will
be invoked: the recipes for all prerequisites of a target will be completed before the recipe
for the target is run. Second, it imposes a dependency relationship: if any prerequisite is
newer than the target, then the target is considered out-of-date and must be rebuilt.
Normally, this is exactly what you want: if a target’s prerequisite is updated, then the
target should also be updated.
Occasionally, however, you have a situation where you want to impose a specific ordering
on the rules to be invoked without forcing the target to be updated if one of those rules is
executed. Inthat case, youwant to define order-only prerequisites. Order-only prerequisites
can be specified by placing a pipe symbol (|) in the prerequisites list: any prerequisites to
the left of the pipe symbol are normal; any prerequisites to the right are order-only:
targets : normal-prerequisites | order-only-prerequisites
The normal prerequisites section may of course be empty. Also, you may still declare
multiple lines of prerequisites for the same target: they are appended appropriately (normal
prerequisites are appended to the list of normal prerequisites; order-only prerequisites are
appended to the list of order-only prerequisites). Note that if you declare the same file to
be both a normal and an order-only prerequisite, the normal prerequisite takes precedence
(since they have a strict superset of the behavior of an order-only prerequisite).
Consider anexample where your targets are to be placed ina separate directory, and that
directory might not exist before make is run. In this situation, you want the directory to
be created before any targets are placed into it but, because the timestamps on directories
change whenever a file is added, removed, or renamed, we certainly don’t want to rebuild
all the targets whenever the directory’s timestamp changes. One way to manage this is with
order-only prerequisites: make the directory an order-only prerequisite on all the targets:
OBJDIR := objdir
OBJS := $(addprefix $(OBJDIR)/,foo.o bar.o baz.o)
$(OBJDIR)/%.o : %.c
$(COMPILE.c) $(OUTPUT_OPTION) $<
all: $(OBJS)
Library SDK class:Online Convert PDF to HTML5 files. Best free online PDF html
Download Free Trial. Convert a PDF file to HTML. Then just wait until the conversion from PDF to HTML is complete and download the file.
www.rasteredge.com
Chapter 4: Writing Rules
23
$(OBJS): | $(OBJDIR)
$(OBJDIR):
mkdir $(OBJDIR)
Now the rule to create the objdir directory will be run, if needed, before any ‘.o’ is
built, but no ‘.o’ will be built because the objdir directory timestamp changed.
4.3 Using Wildcard Characters in File Names
Asingle file name can specify many files using wildcard characters. The wildcard characters
in make are ‘*’, ‘?’ and ‘[...]’, the same as in the Bourne shell. For example, *.c specifies
alist of all the files (in the working directory) whose names end in ‘.c’.
The character ‘~’ at the beginning of a file name also has special significance. If alone,
or followed by a slash, it represents your home directory. For example ~/bin expands to
/home/you/bin. If the ‘~’ is followed by a word, the string represents the home directory
of the user named by that word. For example ~john/bin expands to /home/john/bin. On
systems which don’t have a home directory for each user (suchas MS-DOS or MS-Windows),
this functionality can be simulated by setting the environment variable HOME.
Wildcard expansion is performed by make automatically in targets and in prerequisites.
In recipes, the shell is responsible for wildcard expansion. In other contexts, wildcard
expansion happens only if you request it explicitly with the wildcard function.
The special significance of a wildcard character can be turned off by preceding it with
abackslash. Thus, foo\*bar would refer to a specific file whose name consists of ‘foo’, an
asterisk, and ‘bar’.
4.3.1 Wildcard Examples
Wildcards can be used in the recipe of a rule, where they are expanded by the shell. For
example, here is a rule to delete all the object files:
clean:
rm -f *.o
Wildcards are also useful in the prerequisites of a rule. With the following rule in the
makefile, ‘make print’ will print all the ‘.c’ files that have changed since the last time you
printed them:
print: *.c
lpr -p $?
touch print
This rule uses print as an empty target file; seeSection4.7[EmptyTargetFilestoRecord
Events], page 31. (Theautomaticvariable‘$?’isusedtoprintonlythosefiles s thathave
changed; seeSection10.5.3[AutomaticVariables],page120.)
Wildcard expansion does not happen when you define a variable. Thus, if you write this:
objects = *.o
then the value of the variable objects is the actual string ‘*.o’. However, if you use the
value of objects in a target or prerequisite, wildcard expansion will take place there. If
Library SDK class:C# HTML5 Viewer: Deployment on AzureCloudService
Tutorial about Integrating C# .NET HTML5 Viewer to AzureCloudService Application.
www.rasteredge.com
Library SDK class:DocImage SDK for .NET: HTML Viewer, View, Annotate, Convert, Print
.NET Document Imaging SDK, view, annotate, convert, process, and print Word, Excel, PowerPoint, PDF, TIFF, DICOM, BMP, JPEG, GIF, PNG, JPEG 2000 & JBIG2 in .NET
www.rasteredge.com
24
GNU make
you use the value of objects in a recipe, the shell may perform wildcard expansion when
the recipe runs. To set objects to the expansion, instead use:
objects := $(wildcard *.o)
SeeSection4.3.3[WildcardFunction],page24.
4.3.2 Pitfalls of Using Wildcards
Now here is an example of a naive way of using wildcard expansion, that does not do what
you would intend. Suppose you would like to say that the executable file foo is made from
all the object files in the directory, and you write this:
objects = *.o
foo : $(objects)
cc -o foo $(CFLAGS) $(objects)
The value of objects is the actual string ‘*.o’. Wildcard expansion happens in the rule
for foo, so that each existing ‘.o’ file becomes a prerequisite of foo and will be recompiled
if necessary.
But what if you delete all the ‘.o’ files? When a wildcard matches no files, it is left as it
is, so then foo will depend on the oddly-named file *.o. Since no such file is likely to exist,
make will give you an error saying it cannot figure out how to make *.o. This is not what
you want!
Actually it is possible to obtain the desired result with wildcard expansion, but you need
more sophisticated techniques, including the wildcard function and string substitution.
These are described in the following section.
Microsoft operating systems (MS-DOS and MS-Windows) use backslashes to separate
directories in pathnames, like so:
c:\foo\bar\baz.c
This is equivalent to the Unix-style c:/foo/bar/baz.c (the c: part is the so-called drive
letter). When make runs on these systems, it supports backslashes as well as the Unix-
style forward slashes in pathnames. However, this support does not include the wildcard
expansion, where backslash is a quote character. Therefore, you must use Unix-style slashes
in these cases.
4.3.3 The Function wildcard
Wildcard expansion happens automatically in rules. But wildcard expansion does not nor-
mally take place when a variable is set, or inside the arguments of a function. If you want
to do wildcard expansion in such places, you need to use the wildcard function, like this:
$(wildcard pattern...)
This string, used anywhere in a makefile, is replaced by a space-separated list of names
of existing files that match one of the given file name patterns. If no existing file name
matches a pattern, then that pattern is omitted from the output of the wildcard function.
Note that this is different from how unmatched wildcards behave in rules, where they are
used verbatim rather than ignored (seeSection4.3.2[WildcardPitfall],page24).
One use of the wildcard function is to get a list of all the C source files in a directory,
like this:
Library SDK class:C# powerpoint - Convert PowerPoint to HTML in C#.NET
C# PowerPoint - Convert PowerPoint to HTML in C#.NET. How to Convert PowerPoint to HTML Webpage with C# PowerPoint Conversion SDK.
www.rasteredge.com
Library SDK class:C# Word - Convert Word to HTML in C#.NET
C# Word - Convert Word to HTML in C#.NET. How to Convert Word to HTML Webpage with C# Word Conversion SDK. Word to HTML Conversion Overview.
www.rasteredge.com
Chapter 4: Writing Rules
25
$(wildcard *.c)
We can change the list of C source files into a list of object files by replacing the ‘.c’
suffix with ‘.o’ in the result, like this:
$(patsubst %.c,%.o,$(wildcard *.c))
(Here we have used another function, patsubst. See Section 8.2 [Functions for String
Substitution and Analysis], page 84.)
Thus, a makefile to compile all C source files in the directory andthenlink them together
could be written as follows:
objects := $(patsubst %.c,%.o,$(wildcard *.c))
foo : $(objects)
cc -o foo $(objects)
(This takes advantage of the implicit rule for compiling C programs, so there is no need to
write explicit rules for compiling the files. SeeSection6.2[TheTwoFlavorsofVariables],
page 60,foranexplanationof‘:=’,whichisavariantof‘=’.)
4.4 Searching Directories for Prerequisites
For large systems, it is often desirable to put sources in a separate directory from the
binaries. The directory search features of make facilitate this by searching several directories
automatically to find a prerequisite. When you redistribute the files among directories, you
do not need to change the individual rules, just the search paths.
4.4.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.
Thus, if a file that is listed as a target or prerequisite does not exist in the current
directory, make searches the directories listed in VPATH for a file with that name. If a file is
found in one of them, that file may become the prerequisite (see below). Rules may then
specify the names of files in the prerequisite list as if they allexisted in the current directory.
SeeSection4.4.4[WritingRecipeswithDirectorySearch],page27.
In the VPATH variable, directory names are separated by colons or blanks. The order in
which directories are listed is the order followed by make in its search. (On MS-DOS and
MS-Windows, semi-colons are used as separators of directory names in VPATH, since the
colon can be used in the pathname itself, after the drive letter.)
For example,
VPATH = src:../headers
specifies a path containing two directories, src and ../headers, which make searches in
that order.
With this value of VPATH, the following rule,
foo.o : foo.c
is interpreted as if it were written like this:
Library SDK class:C# WinForms Viewer: Load, View, Convert, Annotate and Edit Excel
software. Powerful conversion function help users to freely implement conversion from Excel document to PDF, Tiff and HTML file.
www.rasteredge.com
Library SDK class:C# WPF Viewer: Load, View, Convert, Annotate and Edit Excel
easily. Besides, powerful conversion function will help users to freely convert Excel document to PDF, Tiff and HTML file. Annotations
www.rasteredge.com
26
GNU make
foo.o : src/foo.c
assuming the file foo.c does not exist in the current directory but is found in the directory
src.
4.4.2 The vpath Directive
Similar to the VPATH variable, but more selective, is the vpath directive (note lower case),
which allows you to specify a search path for a particular class of file names: those that
match a particular pattern. Thus you can supply certain search directories for one class of
file names and other directories (or none) for other file names.
There are three forms of the vpath directive:
vpath pattern directories
Specify the search path directories for file names that match pattern.
The search path, directories, is a list of directories to be searched, separated
by colons (semi-colons on MS-DOS and MS-Windows) or blanks, just like the
search path used in the VPATH variable.
vpath pattern
Clear out the search path associated with pattern.
vpath
Clear all search paths previously specified with vpath directives.
Avpath pattern is a string containing a ‘%’ character. The string must match the file
name of a prerequisite that is being searched for, the ‘%’ character matching any sequence
of zero or more characters (as in pattern rules; see Section10.5[DefiningandRedefining
Pattern Rules], page 118). Forexample,%.hmatchesfilesthatendin.h. . (Ifthereis s no
‘%’, the pattern must match the prerequisite exactly, which is not useful very often.)
‘%’ characters in a vpath directive’s pattern can be quoted with preceding backslashes
(‘\’). Backslashes that would otherwise quote ‘%’ characters can be quoted with more
backslashes. Backslashes that quote ‘%’ characters or other backslashes are removed from
the pattern before it is compared to file names. Backslashes that are not in danger of
quoting ‘%’ characters go unmolested.
When a prerequisite fails to exist in the current directory, if the pattern in a vpath
directive matches the name of the prerequisite file, then the directories in that directive are
searched just like (and before) the directories in the VPATH variable.
For example,
vpath %.h ../headers
tells make to look for any prerequisite whose name ends in .h in the directory ../headers
if the file is not found in the current directory.
If several vpath patterns match the prerequisite file’s name, then make processes each
matching vpath directive one by one, searching all the directories mentioned in each di-
rective. make handles multiple vpath directives in the order in which they appear in the
makefile; multiple directives with the same pattern are independent of each other.
Thus,
Chapter 4: Writing Rules
27
vpath %.c foo
vpath %
blish
vpath %.c bar
will look for a file ending in ‘.c’ in foo, then blish, then bar, while
vpath %.c foo:bar
vpath %
blish
will look for a file ending in ‘.c’ in foo, then bar, then blish.
4.4.3 How Directory Searches are Performed
When a prerequisite is found through directory search, regardless of type (general or se-
lective), the pathname located may not be the one that make actually provides you in the
prerequisite list. Sometimes the path discovered through directory search is thrown away.
The algorithmmake uses todecide whether tokeepor abandona path foundvia directory
search is as follows:
1. If a target file does not exist at the path specified in the makefile, directory search is
performed.
2. If the directory search is successful, that path is kept and this file is tentatively stored
as the target.
3. All prerequisites of this target are examined using this same method.
4. After processing the prerequisites, the target may or may not need to be rebuilt:
a. If the target does not need to be rebuilt, the path to the file found during directory
search is used for any prerequisite lists which contain this target. In short, if make
doesn’t need to rebuild the target then youuse the path found via directory search.
b. If the target does need to be rebuilt (is out-of-date), the pathname found during
directory search is thrown away, and the target is rebuilt using the file name
specified in the makefile. In short, if make must rebuild, then the target is rebuilt
locally, not in the directory found via directory search.
This algorithm may seem complex, but in practice it is quite often exactly what you
want.
Other versions of make use a simpler algorithm: if the file does not exist, and it is found
via directory search, then that pathname is always used whether or not the target needs
to be built. Thus, if the target is rebuilt it is created at the pathname discovered during
directory search.
If, in fact, this is the behavior you want for some or all of your directories, you can use
the GPATH variable to indicate this to make.
GPATH has the same syntax and format as VPATH (that is, a space- or colon-delimited list
of pathnames). If an out-of-date target is found by directory search in a directory that also
appears in GPATH, then that pathname is not thrown away. The target is rebuilt using the
expanded path.
4.4.4 Writing Recipes with Directory Search
When a prerequisite is found in another directory through directory search, this cannot
change the recipe of the rule; they will execute as written. Therefore, you must write the
recipe with care so that it will look for the prerequisite in the directory where make finds it.
28
GNU make
This is done with the automatic variables such as ‘$^’ (see Section10.5.3[Automatic
Variables], page 120). Forinstance,thevalueof‘$^’isalistofalltheprerequisitesofthe
rule, including the names of the directories in which they were found, and the value of ‘$@’
is the target. Thus:
foo.o : foo.c
cc -c $(CFLAGS) $^ -o $@
(The variable CFLAGS exists so you can specify flags for C compilation by implicit rules; we
use it here for consistency so it will affect all C compilations uniformly; see Section10.3
[Variables Used by Implicit Rules], page 115.)
Often the prerequisites include header files as well, which you do not want to mention
in the recipe. The automatic variable ‘$<’ is just the first prerequisite:
VPATH = src:../headers
foo.o : foo.c defs.h hack.h
cc -c $(CFLAGS) $< -o $@
4.4.5 Directory Search and Implicit Rules
The search through the directories specified in VPATH or with vpath also happens during
consideration of implicit rules (seeChapter10[UsingImplicitRules],page111).
For example, when a file foo.o has no explicit rule, make considers implicit rules, such
as the built-in rule to compile foo.c if that file exists. If such a file is lacking in the current
directory, the appropriate directories are searched for it. If foo.c exists (or is mentioned
in the makefile) in any of the directories, the implicit rule for C compilation is applied.
The recipes of implicit rules normally use automatic variables as a matter of necessity;
consequently they will use the file names found by directory search with no extra effort.
4.4.6 Directory Search for Link Libraries
Directory search applies in a special way to libraries used with the linker. This special
feature comes into play when you write a prerequisite whose name is of the form ‘-lname’.
(You can tell something strange is going on here because the prerequisite is normally the
name of a file, and the file name of a library generally looks like libname.a, not like
‘-lname’.)
When a prerequisite’s name has the form ‘-lname’, make handles it specially by searching
for the file libname.so, and, if it is not found, for the file libname.a inthe current directory,
in directories specified by matching vpath search paths and the VPATH searchpath,and then
in the directories /lib, /usr/lib, and prefix/lib (normally /usr/local/lib, but MS-
DOS/MS-Windows versions of make behave as if prefix is defined to be the root of the
DJGPP installation tree).
For example, if there is a /usr/lib/libcurses.a library on your system (and no
/usr/lib/libcurses.so file), then
foo : foo.c -lcurses
cc $^ -o $@
would cause the command ‘cc foo.c /usr/lib/libcurses.a -o foo’ to be executed when
foo is older than foo.c or than /usr/lib/libcurses.a.
Although the default set of files to be searched for is libname.so and libname.a, this
is customizable via the .LIBPATTERNS variable. Each word in the value of this variable is
Chapter 4: Writing Rules
29
apattern string. When a prerequisite like ‘-lname’ is seen, make will replace the percent
in each pattern in the list with name and perform the above directory searches using each
library file name.
The default value for .LIBPATTERNS is ‘lib%.so lib%.a’, which provides the default
behavior described above.
You can turn off link library expansion completely by setting this variable to an empty
value.
4.5 Phony Targets
Aphony target is one that is not really the name of a file; rather it is just a name for a
recipe to be executed when you make an explicit request. There are two reasons to use a
phony target: to avoid a conflict with a file of the same name, and to improve performance.
If you write a rule whose recipe will not create the target file, the recipe will be executed
every time the target comes up for remaking. Here is an example:
clean:
rm *.o temp
Because the rm command does not create a file named clean, probably no such file will
ever exist. Therefore, the rm command will be executed every time you say ‘make clean’.
In this example, the clean target will not work properly if a file named clean is ever
created in this directory. Since it has no prerequisites, clean would always be considered
up to date and its recipe would not be executed. To avoid this problem you can explicitly
declare the target to be phony by making it a prerequisite of the special target .PHONY (see
Section 4.8 [Special Built-in Target Names], page 32)asfollows:
.PHONY: clean
clean:
rm *.o temp
Once this is done, ‘make clean’ will run the recipe regardless of whether there is a file
named clean.
Phony targets are also useful in conjunction with recursive invocations of make (see
Section 5.7 [Recursive Use of make], page 50). Inthis s situation the e makefile will often
contain a variable which lists a number of sub-directories to be built. A simplistic way to
handle this is to define one rule with a recipe that loops over the sub-directories, like this:
SUBDIRS = foo bar baz
subdirs:
for dir in $(SUBDIRS); do \
$(MAKE) -C $$dir; \
done
There are problems with this method, however. First, any error detected in a sub-make
is ignored by this rule, so it will continue to build the rest of the directories even when one
fails. This can be overcome by adding shell commands to note the error and exit, but then
it will do so even if make is invoked with the -k option, which is unfortunate. Second, and
perhaps more importantly, you cannot take advantage of make’s ability to build targets in
parallel (seeSection5.4[ParallelExecution],page47), since there is only one rule.
30
GNU make
By declaring the sub-directories as .PHONY targets (you must do this as the sub-directory
obviously always exists; otherwise it won’t be built) you can remove these problems:
SUBDIRS = foo bar baz
.PHONY: subdirs $(SUBDIRS)
subdirs: $(SUBDIRS)
$(SUBDIRS):
$(MAKE) -C $@
foo: baz
Here we’ve also declared that the foo sub-directory cannot be built until after the baz
sub-directory is complete; this kind of relationship declaration is particularly important
when attempting parallel builds.
The implicit rule search (seeChapter10[ImplicitRules],page111) is skipped for .PHONY
targets. This is why declaring a target as .PHONY is good for performance, even if you are
not worried about the actual file existing.
Aphony target should not be a prerequisite of a real target file; if it is, its recipe will
be run every time make goes to update that file. As long as a phony target is never a
prerequisite of a real target, the phony target recipe will be executed only when the phony
target is a specified goal (seeSection9.2[ArgumentstoSpecifytheGoals],page99).
Phony targets can have prerequisites. When one directory contains multiple programs,
it is most convenient to describe all of the programs in one makefile ./Makefile. Since the
target remade by default will be the first one in the makefile, it is common to make this
aphony target named ‘all’ and give it, as prerequisites, all the individual programs. For
example:
all : prog1 prog2 prog3
.PHONY : all
prog1 : prog1.o utils.o
cc -o prog1 prog1.o utils.o
prog2 : prog2.o
cc -o prog2 prog2.o
prog3 : prog3.o sort.o utils.o
cc -o prog3 prog3.o sort.o utils.o
Now you can say just ‘make’ to remake all three programs, or specify as arguments the ones
to remake (as in ‘make prog1 prog3’). Phoniness is not inherited: the prerequisites of a
phony target are not themselves phony, unless explicitly declared to be so.
When one phony target is a prerequisite of another, it serves as a subroutine of the other.
For example, here ‘make cleanall’ will delete the object files, the difference files, and the
file program:
.PHONY: cleanall cleanobj cleandiff
Documents you may be interested
Documents you may be interested