The different assignment operators have somewhat different meanings.
- =
-
VARIABLE = text string
This is the usual assignment statement that all implementations of make support. The expression on the right hand side is not evaluated until the value of
$(VARIABLE)
is actually used somewhere. Thus, if you do the following:X = 1
Y = $(X)
X = 2Then
$(Y)
later in the makefile will evaluate to “2”. - := (THIS ONE IS PREFERED!!)
-
VARIABLE := expr
This is the same as “VARIABLE = expr” except that the right hand side is evaluated at the time of the assignment. Thus if
X := 1
Y := $(X)
X := 2then
$(Y)
later in the makefile will evaluate to “1” since that's what$(X)
was when$(Y)
was defined. - +=
-
VARIABLE += expr
Appends the string to the previous contents of the variable, separated by a space. If the variable was previously assigned with
:=
, then the right hand side is evaluated before appending.
Generating Prerequisites Automatically
The practice we recommend for automatic prerequisite generation is to have one makefile corresponding to each source file. For each source file name.c there is a makefile name.d which lists what files the object file name.o depends on. That way only the source files that have changed need to be rescanned to produce the new prerequisites.
Here is the pattern rule to generate a file of prerequisites (i.e., a makefile) called name.d from a C source file called name.c:
%.d: %.c
@set -e; rm -f $@; \
$(CC) -M $(CPPFLAGS) $< > $@.$$$$; \
sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
rm -f $@.$$$$
See Pattern Rules, for information on defining pattern rules. The `-e' flag to the shell causes it to exit immediately if the $(CC)
command (or any other command) fails (exits with a nonzero status). With the GNU C compiler, you may wish to use the `-MM' flag instead of `-M'. This omits prerequisites on system header files. See Options Controlling the Preprocessor, for details.
The purpose of the sed
command is to translate (for example):
main.o : main.c defs.h
into:
main.o main.d : main.c defs.h
This makes each `.d' file depend on all the source and header files that the corresponding `.o' file depends on. make
then knows it must regenerate the prerequisites whenever any of the source or header files changes.
Once you've defined the rule to remake the `.d' files, you then use the include
directive to read them all in. See Include. For example:
sources = foo.c bar.c
include $(sources:.c=.d)
(This example uses a substitution variable reference to translate the list of source files `foo.c bar.c' into a list of prerequisite makefiles, `foo.d bar.d'. See Substitution Refs, for full information on substitution references.) Since the `.d' files are makefiles like any others, make
will remake them as necessary with no further work from you. See Remaking Makefiles.
Note that the `.d' files contain target definitions; you should be sure to place the include
directive after the first, default goal in your makefiles or run the risk of having a random object file become the default goal. See How Make Works.
INCLUDE DIRECTIVE
The
include
directive tells make
to suspend reading the current makefile and read one or more other makefiles before continuing. The directive is a line in the makefile that looks like this: include filenames...
filenames can contain shell file name patterns. If filenames is empty, nothing is included and no error is printed. Extra spaces are allowed and ignored at the beginning of the line, but a tab is not allowed. (If the line begins with a tab, it will be considered a command line.) Whitespace is required between include
and the file names, and between file names; extra whitespace is ignored there and at the end of the directive. A comment starting with `#' is allowed at the end of the line. If the file names contain any variable or function references, they are expanded. See How to Use Variables.
For example, if you have three .mk files, a.mk, b.mk, and c.mk, and $(bar)
expands to bish bash
, then the following expression
include foo *.mk $(bar)
is equivalent to
include foo a.mk b.mk c.mk bish bash
When make
processes an include
directive, it suspends reading of the containing makefile and reads from each listed file in turn. When that is finished, make
resumes reading the makefile in which the directive appears.
One occasion for using include
directives is when several programs, handled by individual makefiles in various directories, need to use a common set of variable definitions (see Setting Variables) or pattern rules (see Defining and Redefining Pattern Rules).
Another such occasion is when you want to generate prerequisites from source files automatically; the prerequisites can be put in a file that is included by the main makefile. This practice is generally cleaner than that of somehow appending the prerequisites to the end of the main makefile as has been traditionally done with other versions of make
. See Automatic Prerequisites. If the specified name does not start with a slash, and the file is not found in the current directory, several other directories are searched. First, any directories you have specified with the `-I' or `--include-dir' option are searched (see Summary of Options). Then the following directories (if they exist) are searched, in this order: prefix/include (normally /usr/local/include 1) /usr/gnu/include, /usr/local/include, /usr/include.
If an included makefile cannot be found in any of these directories, a warning message is generated, but it is not an immediately fatal error; processing of the makefile containing the include
continues. Once it has finished reading makefiles, make
will try to remake any that are out of date or don't exist. See How Makefiles Are Remade. Only after it has tried to find a way to remake a makefile and failed, will make
diagnose the missing makefile as a fatal error.
If you want make
to simply ignore a makefile which does not exist and cannot be remade, with no error message, use the -include
directive instead of include
, like this:
-include filenames...
HOW MAKE WORKS
How make
Processes a Makefile
By default, make
starts with the first target (not targets whose names start with `.'). This is called the default goal. (Goals are the targets that make
strives ultimately to update. You can override this behavior using the command line (see Arguments to Specify the Goals) or with the .DEFAULT_GOAL
special variable (see Other Special Variables). In the simple example of the previous section, the default goal is to update the executable program edit; therefore, we put that rule first.
Thus, when you give the command:
make
make
reads the makefile in the current directory and begins by processing the first rule. In the example, this rule is for relinking edit; but before make
can fully process this rule, it must process the rules for the files that edit depends on, which in this case are the object files. Each of these files is processed according to its own rule. These rules say to update each `.o' file by compiling its source file. The recompilation must be done if the source file, or any of the header files named as prerequisites, is more recent than the object file, or if the object file does not exist.
The other rules are processed because their targets appear as prerequisites of the goal. If some other rule is not depended on by the goal (or anything it depends on, etc.), that rule is not processed, unless you tell make
to do so (with a command such as make clean
).
Before recompiling an object file, make
considers updating its prerequisites, the source file and header files. This makefile does not specify anything to be done for them—the `.c' and `.h' files are not the targets of any rules—so make
does nothing for these files. But make
would update automatically generated C programs, such as those made by Bison or Yacc, by their own rules at this time.
After recompiling whichever object files need it, make
decides whether to relink edit. This must be done if the file edit does not exist, or if any of the object files are newer than it. If an object file was just recompiled, it is now newer than edit, so edit is relinked. Thus, if we change the file insert.c and run make
, make
will compile that file to update insert.o, and then link edit. If we change the file command.h and run make
, make
will recompile the object files kbd.o, command.o and files.o and then link the file edit.
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.