Makefiles - Macros and More

LeftRight

The previous examples generally have a lot of repetitive text. make provides a simple macro mechanism. Macros are defined in a number of ways (listed in increasing order of precedence):

  1. Internally defined by make
  2. Shell environment variables
    	setenv CC "gcc"
    
  3. Macros defined in the Makefile:
    OBJS	= main.o sub1.o sub2.o sub3.o
    
    There can be no <tab>s before the macro name and no colons before the equal (=) sign.
  4. Macros can be defined on the command-line:
    	make CC=gcc
    

There is a special circumstance (using the -e option) when the second and third entries in the list are swapped in precedence.

Macros are used in the Makefile by bracketing the macro name with either parentheses ``()'' or braces ``{}'' and prepending a dollar sign ``$''. If the macro name is a single character the parentheses and braces can be neglected. This is a likely source of errors in Makefiles.

By convention macro names should be uppercase, but lowercase letters, numbers and underscores are safe to use also.

If a macro name is not defined make will just use a null string instead and not complain. This is not an error.

Can Not Dynamically Reset Macros

One of the problems with macros is that, unlike a script, macros can not be reassigned a different value halfway through the processing. A macro can not have one value when operating on one target and a different value for another. ``Why?'' This highlights the difference between scripts and make. Scripts are executed in a linear fashion where there is a clear sequence of events to execute. make, on the other hand, defines an inverted tree structure of dependencies with associated commands to create targets. The tree can be traversed either depth-first or level descent; therefore, the order of operations is not necessarily linear. make must read through the entire Makefile before starting any dependency analysis. The last macro declaration defines the overall macro definition to be used everywhere.

There are ways to get around this limitation by using a recursive make invocation. However, for most applications it won't be necessary if you design your Makefile script accordingly.

Predefined and Internal Macros

make has several predefined macros that makes rule writing easier and more generalized. However, be careful. The accidental substitution of the wrong macro may cause the overwriting of the source file. In particular, if $< or $? is used when $@ should have been used in the action. The macros of most interest are:
$@ the name of the file to be ``made''
$? the set of dependent names that are younger than the target
$< the name of the related file that caused the action (the precursor to the target) - this is only for suffix rules
$* the shared prefix of the target and dependent - only for suffix rules
$$ escapes macro substitution, returns a single ``$''.
Suffix rules will be discussed later.

The following example Makefile demonstrates some of these special macros:


# tests of the various built-in macros SRCS = aaa.c bbb.c ccc.c OBJS = ${SRCS:.c=.o} .SILENT : all : xxx yyy xxx : $(SRCS) echo "target ======== $@" echo "all sources = $(SRCS)" echo "newer sources = $?" echo "all objects = $(OBJS)" yyy : *.c echo "target ======== $@" echo "all sources = $(SRCS)" echo "newer sources = $?"
Which gives the following output:
% make
target ======== xxx
all   sources = aaa.c bbb.c ccc.c
newer sources = aaa.c bbb.c ccc.c
all   objects = aaa.o bbb.o ccc.o
target ======== yyy
all   sources = aaa.c bbb.c ccc.c
newer sources = aaa.c bbb.c ccc.c xxx.c
The above example shows a couple of new features.

Editing Macros

The first is the limited macro substitution
OBJS    = ${SRCS:.c=.o}
Which says to substitute ``.o'' for the last two characters, if they happen to be ``.c'', in the list given by $(SRCS). This provides an easy way to create lists of object files, man page files, executables, etc. from a single list of sources. However, not every make allows this type of substitution. (The Cray, IBM SP, and GNU ones do.)

Dependency Globbing

The target or prerequisites could use file ``globbing'' symbols. The above example shows the prerequisites for yyy as *.c, where * matches any number of characters. The other globbing character is ?, which matches any single character. Note that this does not work reliably if the target uses globbing characters. It works for GNU make, but not for the Cray or IBM SP. It's generally not a good idea to use globbing at all and I have rarely seen Makefiles with it.

Hosts of Other Macros

There are a number of built-in macros, and they can be listed out with all the various suffix rules and environment variables with:
make -p -f /dev/null
The ones I consider to be the most import are:
SHELL
The shell to use for executing commands. Some makes don't honor it and use /bin/sh anyways. Others will take the users login shell. You should always set this macro and define it to /bin/sh and write your actions appropriately.
MAKE
the name of the make command. Only GNU uses the full pathname if specified on the command-line, else just uses command name. Therefore, need to make sure the desired make is found first in the command PATH if trying to use another version of make.
MAKEFLAGS or MFLAGS
the options passed to the Makefile. However, it's not done consistently. GNU and Cray pass only the option letters collected together (e.g. ni). IBM SP passes dashed options each separate (e.g. -n -i). GNU puts the dashed options into MFLAGS, a macro not used by the other two!
VPATH
a colon (:) separated path of directories to search for prerequisites.

There are numerous macros that refer to various compilers and tools with their associated macro for passing options.

Macro Flags Tool
FC/CF/F77 FFLAGS Fortran compiler
CC CFLAGS C compiler
AS ASFLAGS assembler
LD LDFLAGS object loader
AR ARFLAGS archiver
LEX LFLAGS lexical parser
YACC YFLAGS grammar parser

This is just a small portion. Except for the Fortran compiler, the rest listed are fairly standard to each implementation. These macros are used by the suffix rules described in the next section.

LeftRight
Slide 4