Sunday, September 9, 2012

A Makefile practical example


It's not uncommon in a project to have a standard rule for compiling files (perhaps even using the built-in GNU Make rule) and to need to have a slightly different version of that rule for a specific file, or set of files, that otherwise use the same command.

For example, here's a Makefile that builds all the C files in two subdirectories (lib1 and lib2) using a pattern rule.

lib1_SRCS := $(wildcard lib1/*.c)
lib2_SRCS := $(wildcard lib2/*.c)

lib1_OBJS := $(lib1_SRCS:.c=.o)
lib2_OBJS := $(lib2_SRCS:.c=.o)

.PHONY: all
all: $(lib1_OBJS) $(lib2_OBJS)

%.o: %.c
   @$(COMPILE.C) -o $@ $<

First the Makefile gets the list of all C files in lib1 in the variable lib1_SRCS and the C files in lib2 in lib2_SRCS and then it converts those to a list of object files to build using a substitution reference to change .c to .o creating lib1_OBJS and lib2_OBJS.

The pattern rule uses the GNU Make built-in variable COMPILE.C to run a compiler that compiles a .c into a .o.   The Makefile knows to build all the objects in lib1_OBJS and lib2_OBJS because they are prerequisites of all.

This works fine if all the .c files have the same compilation options.

Now suppose that the C file lib1/special.c requires the -Wcomment option to prevent the compiler from warning about an oddly written comment.   Obviously is would be possible to change the value of CPPFLAGS globally by adding

CPPFLAGS += -Wcomment

in the Makefile.  But that change affects every compilation and is probably undesirable.

Luckily, a target-specific variable can be used to just alter the value of CPPFLAGS for that single file.  By writing

lib1/special.o: CPPFLAGS += -Wcomment

the value of CPPFLAGS will be altered just for the creation of lib1/special.o.

Now suppose that an entire subdirectory requires a special CPPFLAGS option to maximize optimization for speed (the -fast option to gcc, for example).

Here a pattern-specific macro definition is ideal.  Adding

lib1/%.o: CPPFLAGS += -fast

does the trick.  Any .o files that are built in lib1/ will have the -fast command-line option.

Conclusion

Target-specific and pattern-specific macros are worth reading about because they are a very handy feature of GNU Make when a small change is needed for a limited set of targets.

Further reading can be found in the GNU Make manual sections 'Target-specific Variable Values' (http://www.gnu.org/software/make/manual/make.html#Target_002dspecific) and 'Pattern-specific Variable Values' (http://www.gnu.org/software/make/manual/make.html#Pattern_002dspecific).

No comments:

Post a Comment