• 12301阅读
  • 0回复

make 英文文档 [复制链接]

上一主题 下一主题
离线ppking
 

只看楼主 倒序阅读 楼主  发表于: 2005-08-24
make Utility
This chapter describes the make utility, which includes:
 Hidden dependency checking
 Command dependency checking
 Pattern-matching rules
 Automatic retrieval of SCCS files
This version of the make utility runs successfully with makefiles written for
previous versions of make. Makefiles that rely on enhancements might not be
compatible with other versions of this utility (see Appendix A, “System V make” for
more information on previous versions of make). Refer to “make Enhancements
Summary ” on page 168 for a complete summary of enhancements and compatibility
issues.
make streamlines the process of generating and maintaining object files and
executable programs. It helps compile programs consistently and eliminates
unnecessary recompilation of modules that are unaffected by source code changes.
make provides features that simplify compilations. You can also use it to automate
any complicated or repetitive task that is not interactive. You can use make to update
and maintain object libraries, to run test suites, and to install files onto a file system
or tape. In conjunction with SCCS, you can use make to ensure that a large software
project is built from the desired versions in an entire hierarchy of source files.
make reads a file that you create, called a makefile, which contains information about
what files to build and how to build them. After you write and test the makefile,
you can forget about the processing details; make takes care of them.
Dependency Checking: make vs. Shell
Scripts
While it is possible to use a shell script to assure consistency in trivial cases, scripts
to build software projects are often inadequate. On the one hand, you don’t want to
wait for a simple minded script to compile every single program or object module
when only one of them has changed. On the other hand, having to edit the script for
each iteration can defeat the goal of consistency. Although it is possible to write a
script of sufficient complexity to recompile only those modules that require it, make
does this job better.
make allows you to write a simple, structured listing of what to build and how to
build it. It uses the mechanism of dependency checking to compare each module with
the source or intermediate files it derives from. make only rebuilds a module if one
or more of these prerequisite files, called dependency files, has changed since the
module was last built.
To determine whether a derived file is out of date with respect to its sources, make
compares the modification time of the (existing) module with that of its dependency
file. If the module is missing, or if it is older than the dependency file, make
considers it to be out of date, and issues the commands necessary to rebuild it. A
module can be treated as out of date if the commands used to build it have changed.
Because make does a complete dependency scan, changes to a source file are
consistently propagated through any number of intermediate files or processing
steps. This lets you specify a hierarchy of steps in a top-to-bottom fashion.
You can think of a makefile as a recipe. make reads the recipe, decides which steps
need to be performed, and executes only those steps that are required to produce the
finished module. Each file to build, or step to perform, is called a target. The
makefile entry for a target contains its name, a list of targets on which it depends,
and a list of commands for building it.
The list of commands is called a rule. make treats dependencies as prerequisite
targets, and updates them (if necessary) before processing its current target. The rule
for a target need not always produce a file, but if it does, the file for which the target
is named is referred to as the target file. Each file from which a target is derived (for
example, the file the target depends on) is called a dependency file.
If the rule for a target produces no file by that name, make performs the rule and
considers the target to be up-to-date for the remainder of the run.
make assumes that only it will make changes to files being processed during the
current run. If a source file is changed by another process while make is running, the
files it produces might be in an inconsistent state.
Writing a Simple Makefile
The basic format for a makefile target entry is:
TABLE 4–1 Makefile Target Entry Format
target . . . : [ dependency ...]
[ command ]
...
In the first line, the list of target names is terminated by a colon. This, in turn, is
followed by the dependency list, if there is one. If several targets are listed, this
indicates that each such target is to be built independently using the rule supplied.
Subsequent lines that start with a TAB are taken as the command lines that comprise
the target rule. A common error is to use SPACE characters instead of the leading
TAB.
Lines that start with a # are treated as comments up until the next (unescaped)
NEWLINE and do not terminate the target entry. The target entry is terminated by the
next non-empty line that begins with a character other than TAB or #, or by the end
of the file.
A trivial makefile might consist of just one target shown in the following figure:
TABLE 4–2 A Trivial Makefile
test:
ls test
touch test
When you run make with no arguments, it searches first for a file named makefile,
or, if there is no file by that name, Makefile. If either of these files is under SCCS
control, make checks the makefile against its history file. If it is out of date, make
extracts the latest version.
If make finds a makefile, it begins the dependency check with the first target entry
in that file. Otherwise, you must list the targets to build as arguments on the
command line. make displays each command it runs while building its targets.
$ make
ls test
test not found
touch test
ls test
test
Because the file test was not present (and therefore out of date), make performed the
rule in its target entry. If you run make a second time, it issues a message indicating
that the target is now up to date and skips the rule:
$ make
‘test’ is up to date.
Note - make invokes a Bourne shell to process a command line if that line contains
any shell metacharacters, such as a semicolon ( redirection symbols (<, >, >>, |),
substitution symbols (*, ?, [], $, =), or quotes, escapes or comments (", ’, ‘, \, #,
etc., If a shell is not required to parse the command line, make exec()’s the
command directly.
Line breaks within a rule are significant in that each command line is performed by a
separate process or shell.
This means that a rule such as:
test:
cd /tmp
pwd
behaves differently than you might expect, as shown below.
$ make test
cd /tmp
pwd
/usr/tutorial/waite/arcana/minor/pentangles
You can use semicolons to specify a sequence of commands to perform in a single
shell invocation:
test:
cd /tmp ; pwd
Or, you can continue the input line onto the next line in the makefile by escaping
the NEWLINE with a backslash (\). The escaped NEWLINE is treated as white space
by make.
The backslash must be the last character on the line. The semicolon is required by the
shell.
test:
cd /tmp ; \
pwd
Basic Use of Implicit Rules
When no rule is given for a specified target, make attempts to use an implicit rule to
build it. When make finds a rule for the class of files the target belongs to, it applies
the rule listed in the implicit rule target entry.
In addition to any makefile(s) that you supply, make reads in the default
makefile, /usr/share/lib/make/make.rules, which contains the target
entries for a number of implicit rules, along with other information.
Note - Implicit rules were hand-coded in earlier versions of make.
There are two types of implicit rules: Suffix and Pattern-matching. Suffix rules specify
a set of commands for building a file with one suffix from another file with the same
base name but a different suffix. Pattern-matching rules select a rule based on a
target and dependency that match respective wild-card patterns. The implicit rules
provided by default are suffix rules.
In some cases, the use of suffix rules can eliminate the need for writing a makefile
entirely. For instance, to build an object file named functions.o from a single C
source file named functions.c, you could use the command:
$ make functions.o
cc -c functions.c -o functions.o
This would work equally well for building the object file nonesuch.o from the
source file nonesuch.c.
To build an executable file named functions (with a null suffix) from functions.c,
you need only type the command:
$ make functions
cc -o functions functions.c
The rule for building a .o file from a .c file is called the .c.o (pronounced
“dot-see-dot-oh”) suffix rule. The rule for building an executable program from a .c
file is called the .c rule. The complete set of default suffix rules is listed in Table 4–8.
Processing Dependencies
After make begins, it processes targets as it encounters them in its depth-first
dependency scan. For example, with the following makefile:
batch: a b
touch batch
b:
touch b
a:
touch a
c:
echo "you won’t see me"
make starts with the target batch. Since batch has some dependencies that have
not been checked, namely a and b, make defers batch until after it has checked a
and b against any dependencies they might have.
batch
a b
Since a has no dependencies, make processes it; if the file is not present, make
performs the rule in its target entry.
$ make
touch a
...
Next, make works its way back up to the parent target batch. Since there is still an
unchecked dependency b, make descends to b and checks it.
batch
a b
balso has no dependencies, so make performs its rule:
...
touch b
...
Finally, now that all of the dependencies for batch have been checked and built (if
needed), make checks batch.
batch
Since it rebuilt at least one of the dependencies for batch, make assumes that batch
is out of date and rebuilds it; if a or b had not been built in the current make run,
but were present in the directory and newer than batch, make’s time stamp
comparison would also result in batch being rebuilt:
...
touch batch
Target entries that are not encountered in a dependency scan are not processed.
Although there is a target entry for c in the makefile, make does not encounter it
while performing the dependency scan for batch, so its rule is not performed. You
can select an alternate starting target like c by entering it as an argument to the
make command.
In the next example, the batch target produces no file. Instead, it is used as a label
to group a set of targets.
batch: a b c
a: a1 a2
touch a
b:
touch b
c:
touch c
a1:
touch a1
a2:
touch a2
In this case, the targets are checked and processed, as shown in the following
diagram:
batch
a bc
a1 a 2
Essentially, make then:
1. Checks batch for dependencies, notices that there are three, and so defers it.
2. Checks a, the first dependency, and notices that it has two dependencies of its
own. Continuing in like fashion, make:
a. Checks a1, and if necessary, rebuilds it.
b. Checks a2, and if necessary, rebuilds it.
3. Determines whether to build a.
4. Checks b and rebuilds it if necessary.
5. Checks and rebuilds c if necessary.
6. After traversing its dependency tree, make checks and processes the topmost
target, batch.Ifbatch contains a rule, make performs that rule. Here batch has
no rule, therefore make performs no action, but notes that batch has been rebuilt;
any targets depending on batch would also be rebuilt.
Null Rules
If a target entry contains no rule, make attempts to select an implicit rule to build it.
If make cannot find an appropriate implicit rule and there is no SCCS history from
which to retrieve it, make concludes that the target has no corresponding file, and
regards the missing rule as a null rule.
Note - You can use a dependency with a null rule to force the target rule to be
executed. The conventional name for such is FORCE.
With this makefile:
haste: FORCE
echo "haste makes waste"
FORCE:
make performs the rule for making haste, even if a file by that name is up to date:
$ touch haste
$ make haste
echo "haste makes waste"
haste makes waste
Special Targets
make has several built-in special targets that perform special functions. For example,
the .PRECIOUS special target directs make to preserve library files when make is
interrupted.
Special targets:
 Begin with a period (.)
 Have no dependencies
 Can appear anywhere in a makefile
Table 4–3 includes a list of special targets.
Unknown Targets
If a target is named either on the command line or in a dependency list, and it
 Is not a file present in the working directory
 Has no target or dependency entry
 Does not belong to a class of files for which an implicit rule is defined
 Has no SCCS history file, and
 There is no rule specified for the .DEFAULT special target
Then make stops processing and issues an error message.
$ make believe
make: Fatal error: Don’t know how to make target ‘believe’.
Note - However, if the -k option is in effect, make continues with the other targets
that do not depend on the one in which the error occurred.
Duplicate Targets
Targets can appear more than once in a makefile. For example,
foo: dep_1
foo: dep_2
foo:
touch foo
is the same as
foo: dep_1 dep_2
touch foo
However, many people feel that it’s preferable to have a target appear only once, for
ease of reading.
Reserved make Wor ds
The words in the following table are reserved by make:
TABLE 4–3 Reserved make Words
.BUILT_LAST_MAKE_RUN .DEFAULT .DERIVED_SRC
.DONE .IGNORE .INIT
.KEEP_STATE .MAKE_VERSION .NO_PARALLEL
.PRECIOUS .RECURSIVE .SCCS_GET
.SILENT .SUFFIXES .WAIT
FORCE HOST_ARCH HOST_MACH
KEEP_STATE MAKE MAKEFLAGS
MFLAGS TARGET_ARCH TARGET_MACH
VERSION_1.0 VIRTUAL_ROOT VPATH
Running Commands Silently
You can inhibit the display of a command line within a rule by inserting an @ as the
first character on that line. For example, the following target:
quiet:
@echo you only see me once
produces:
$ make quiet
you only see me once
If you want to inhibit the display of commands during a particular make run, you
can use the -s option. If you want to inhibit the display of all command lines in
every run, add the special target .SILENT to your makefile.
.SILENT:
quiet:
echo you only see me once
Special-function targets begin with a dot (.). Target names that begin with a dot are
never used as the starting target, unless specifically requested as an argument on the
command line. make normally issues an error message and stops when a command
returns a nonzero exit code. For example, if you have the target:
rmxyz:
rm xyz
and there is no file named xyz, make halts after rm returns its exit status.
$ ls xyz
xyz not found
$ make rmxyz
rm xyz
rm: xyz: No such file or directory
*** Error code 1
make: Fatal error: Command failed for target ‘rmxyz’
Note - If - and @ are the first two such characters, both take effect.
To continue processing regardless of the command exit code, use a dash character (-)
as the first non-TAB character:
rmxyz:
-rm xyz
In this case you get a warning message indicating the exit code make received:
$make rmxyz
rm xyz
rm: xyz: No such file or directory
*** Error code 1 (ignored)
Note - Unless you are testing a makefile, it is usually a bad idea to ignore
non-zero error codes on a global basis
Although it is generally ill-advised to do so, you can cause make to ignore error
codes entirely with the -i option. You can also cause make to ignore exit codes when
processing a given makefile, by including the .IGNORE special target, though this
too should be avoided.
If you are processing a list of targets, and you want make to continue with the next
target on the list rather than stopping entirely after encountering a non-zero return
code, use the -k option.
Automatic Retrieval of SCCS Files
When source files are named in the dependency list, make treats them like any other
target. Because the source file is presumed to be present in the directory, there is no
need to add an entry for it to the makefile.
When a target has no dependencies, but is present in the directory, make assumes
that file is up to date. If, however, a source file is under SCCS control, make does
some additional checking to ensure that the source file is up to date. If the file is
missing, or if the history file is newer, make automatically issues the following
command to retrieve the most recent version:
sccs get -s filename -Gfilename
Note - With other versions of make, automatic sccs retrieval was a feature only
of certain implicit rules. Also, unlike earlier versions, make only looks for history (s.)
files in the sccs directory; history files in the current working directory are ignored.
However, if the source file is writable by anyone, make does not retrieve a new
version.
$ ls SCCS/*
SCCS/s.functions.c
$ rm -f functions.c
$ make functions
sccs get -s functions.c -Gfunctions.c
cc -o functions functions.c
make checks the time stamp of the retrieved version against the time stamp of the
history file. It does not check to see if the version present in the directory is the most
recently checked-in version. So, if someone had done a get by date (sccs get -c),
make would not discover this fact, and you might unwittingly build an older version
of the program or object file. To be absolutely sure that you are compiling the latest
version, you can precede make with an sccs get SCCS‘ or an sccs clean
command.
Suppressing SCCS Retrieval
The command for retrieving SCCS files is specified in the rule for the .SCCS_GET
special target in the default makefile. To suppress automatic retrieval, simply add
an entry for this target with an empty rule to your makefile:
# Suppress sccs retrieval.
.SCCS_GET:
Passing Parameters: Simple make Macros
The make macro substitution comes in handy when you want to pass parameters to
command lines within a makefile. Suppose that you want to compile an optimized
version of the program program, using the cc -O option. You can lend this sort of
exibility to your makefile by adding a macro reference, such as the following
example, to the target for functions:
functions: functions.c
cc $(CFLAGS) -o functions functions.c
The macro reference acts as a placeholder for a value that you define, either in the
makefile itself, or as an argument to the make command. If you then supply make
with a definition for the CFLAGS macro, make replaces its references with the value
you have defined.
$rm functions
$ make functions "CFLAGS= -O"
cc -O -o functions functions.c
Note - There is a reference to the CFLAGS macro in both the .c and the .c.o
implicit rules.
Note - The command-line definition must be a single argument, hence the quotes in
this example.
If a macro is undefined, make expands its references to an empty string.
You can also include macro definitions in the makefile itself. A typical use is to set
CFLAGS to -O, so that make produces optimized object code by default:
CFLAGS= -O
functions: functions.c
cc $(CFLAGS) -o functions functions.c
A macro definition supplied as a command line argument to make overrides other
definitions in the makefile. Conditionally defined macros are an exception to this.
For instance, to compile functions for debugging with dbx or dbxtool, you can
define the value of CFLAGS to be -g on the command line:
$ rm functions
$ make CFLAGS=-g
cc -g -o functions functions.c
To compile a profiling variant for use with gprof, supply both -O and -pg in the
value for CFLAGS.
A macro reference must include parentheses when the name of the macro is longer
than one character. If the macro name is only one character, the parentheses can be
omitted. You can use curly braces, { and }, instead of parentheses. For example, ‘$X’,
‘$(X)’, and ‘${X}’ are equivalent.
快速回复
限100 字节
 
上一个 下一个