GNU Make has one other directive, which is not actually a
conditional, though it is processed in the same pass as the conditionals
and has some noteworthy interactions with them:
include file-name ...
Example 5.28: Format of a Make include directive
Again, in parallel with the C preprocessor, before the effective
contents of the Makefile are parsed, Make's include
directive is effectively replaced by the listed file-name
contents. Any variable references in the list are expanded before the
filenames are opened, and since the names are delimited with whitespace,
a single referenced variable can safely contain more than one
file-name. This does mean, however, that there is no way to
specify a file-name containing a space.
If file-name is a relative path, such as ../vars.mk
,
instead of a fully qualified path like /usr/share/make/make.std
,
and cannot be found by starting in the current directory, Make tries
to find the file in directories in the include search path.
Voir Invoking Make, for details about setting the include search path.
If a file-name still cannot be found, then Make will issue a
warning:
Makefile:1: Make.depend: No such file or directory
If any included file-name was not found, but has a corresponding
target rule, Make will issue these warnings, but then try to build
the missing files and continue. This is easiest explained by enhancing
our Makefile
. As with any non-trivial project, there are many
interdependencies between the various source files that comprise the
GNU M4 package. In the Makefile
we have been looking at so
far in this chapter, each of the m4_OBJECTS
files depends on
parts of ../lib/libm4.a
. In fact, it is important that the
objects be refreshed if they become out of date with respect to those
parts they depend on...
Maintaining the dependencies between files is time consuming and error
prone. UNIX comes with a tool called makedepend
, which
will automatically discover the dependencies for us, and we can put it
to good use here:
MAKEDEPEND = makedepend DEPEND_FRAGMENT= Make.depend include $(DEPEND_FRAGMENT) CC = gcc CFLAGS = -ggdb3 CPPFLAGS = -DDEBUG=1 m4_SOURCES = main.c freeze.c stackovf.c m4_OBJECTS = main.o freeze.o stackovf.o m4_LIBS = ../lib/libm4.a .SUFFIXES: .SUFFIXES: .c .o m4: $(m4_OBJECTS) $(m4_LIBS) $(CC) $(CFLAGS) -o m4 $(m4_OBJECTS) $(m4_LDADD) $(LIBS) .c.o: $(CC) $(CFLAGS) $(CPPFLAGS) -c $< $(DEPEND_FRAGMENT): $(m4_SOURCES) $(MAKEDEPEND) $(CPPFLAGS) -f $(DEPEND_FRAGMENT) $(m4_SOURCES)
Example 5.29: Automatic file dependencies with Make
Now, we are trying to include
a Makefile fragment which contains
the generated dependency list. But rather than manually generating it,
we have also added a new rule which uses the makedepend
utility to write the dependencies to Make.depend
. Now, even
though Make initially warns us if it cannot include
Make.depend
, before giving up it will try to build the file
itself, and then reread the original Makefile
.
Notice that we have made the depend-fragment file dependent upon the
source files it scans, so that if they change, Make.depend
will
be refreshed. The first time Makefile
is used after adding these
new items, when Make.depend
does not yet exist, you will see the
following:
$ make Makefile:4: Make.depend: No such file or directory makedepend -DDEBUG=1 -f Make.depend main.c freeze.c stackovf.c cp: Make.depend: No such file or directory Appending dependencies to Make.depend make: `m4' is up to date.
Make eventually created its own Make.depend
, and now knows how to
regenerate it if any of the sources whose dependencies it contains are
changed!
You will be able to find more details about the makedepend
command in your system manual pages, with man makedepend.