Previous Page
Next Page

19.10. Directives

We have already introduced the define directive, which produces a simply expanded variable or a function. Other make directives allow you to influence the effective contents of your makefiles dynamically by making certain lines in a makefile dependent on variable conditions, or by inserting additional makefiles on the fly.

19.10.1. Conditionals

You can also make part of your makefile conditional upon the existence of a variable by using the ifdef or ifndef directive. They work the same as the C preprocessor directives of the same names, except that in make, an undefined variable is the same as one whose value is empty. Here is an example:

OBJ = circle.o
LIB = -lm
 
ifdef SHAREDLIBS
  LIB += circulararea.so
else
  OBJ += circulararea.o
endif
 
circle: $(OBJ) $(LIB)
        $(CC) -o $@ $^
 
%.so : %.o
       $(CC) -shared -o $@ $<

As the example shows, the variable name follows ifdef or ifndef without a dollar sign or parentheses. The makefile excerpt shown here defines a rule to link object files into a shared library if the variable SHAREDLIBS has been defined. You might define such a general build option in an environment variable, or on the command line, for example.

You can also make certain lines of the makefile conditional upon whether two expressionsusually the value of a variable and a literal stringare equal. The ifeq and ifneq directives test this condition. The two operands whose equality is the condition to test are either enclosed together in parentheses and separated by a comma, or enclosed individually in quotation marks and separated by whitespace. Here is an example:

ifeq ($(MATHLIB), /usr/lib/libm.so)
  # ... Special provisions for this particular math library ...
endif

That conditional directive, with parentheses, is equivalent to this one with quotation marks:

ifeq "$(MATHLIB)" "/usr/lib/libm.so"
  # ... Special provisions for this particular math library ...
endif

The second version has one strong advantage: the quotation marks make it quite clear where each of the operands begins and ends. In the first version, you must remember that whitespace within the parentheses is significant, except immediately before and after the comma (see also the section "Variables and Whitespace," earlier in this chapter).

make's handling of whitespace in the ifeq and ifneq directives is not the same as in function calls!


19.10.2. Includes

The include directive serves the same purpose as its C preprocessor counterpart, but works slightly differently. To start with an example, you might write a makefile named defaults.mk with a set of standard variables for your environment, containing something like this:

BINDIR = /usr/bin
HOMEBINDIR = ~/bin
SRCDIR = project/src
BUILDDIR = project/obj
 
RM = rm -f
MKDIR = mkdir -p
# ... etc. ...

Then you could add these variables to any makefile by inserting this line:

include defaults.mk

The include keyword may be followed by more than one filename. You can also use shell wildcards like * and ?, and reference make variables to form filenames:

include $(HOMEBINDIR)/myutils.mk $(SRCDIR)/*.mk

For included files without an absolute path, make searches in the current working directory first, then in any directories specified with the -I option on the command line, and then in standard directories determined when make was compiled.

If make fails to find a file named in an include directive, it continues reading the makefile, and then checks to see whether there is a rule that will build the missing file. If so, make rereads the whole makefile after building the included file. If not, make exits with an error. The -include directive (or its synonym sinclude) is more tolerant: it works the same as include, except that make ignores the error and goes on working if it can't find or build an included file.

19.10.3. Other Directives

Of the other four make directives, three are used to control the interplay between make's internal variables and the shell environment, while the fourth instructs make where to look for specific kinds of files. These directives are:


override variable_assignment

Ordinarily, variables defined on the command line take precedence over definitions or assignments with the same name in a makefile. Prefixing the override keyword makes an assignment in a makefile take precedence over the command line. The variable_assignment may use the =, :=, or += operator, or the define directive.


export [ variable_name | variable_assignment]

You can prefix export to a variable assignment or to the name of a variable that has been defined to export that variable to the environment, so that programs invoked by command scripts (including recursive invocations of make) can read it.

The export directive by itself on a line exports all make variables to the environment.

make does not export variables whose names contain any characters other than letters, digits, and underscores. The values of variables you export from makefiles may contain characters that are not allowed in shell environment variables. Such values will probably not be accessible by ordinary shell commands. Nonetheless, child instances of make itself can inherit and use them.


The make variables SHELL and MAKEFLAGS, and also MAKEFILES if you have assigned it a value, are exported by default. Any variables which the current instance of make acquired from the environment are also passed on to child processes.


unexport variable_name

Use the unexport directive to prevent a variable from being exported to the environment. The unexport directive always overrides export.


vpath pattern directory[: directory[: ...]]

The pattern in this directive is formed in the same way as in make pattern rules, using one percent sign (%) as a wildcard character. Whenever make needs a file that matches the pattern, it looks for it in the directories indicated, in the order of their appearance. An example:

vpath  %.c  $(MYPROJECTDIR)/src
vpath  %.h  $(MYPROJECTDIR)/include:/usr/include

On Windows, the separator character in the directory list is a semicolon, not a colon.


Previous Page
Next Page