Noeud:Make Include Directive, Noeud « Up »:Make Conditionals



Make Include Directive

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.