Makefiles - Redefining Macros

LeftRight

Resetting Macros For Different Conditions

In an earlier section it was stated that macros could not be redefined dynamically within a Makefile. The last setting for a macro is the value used through out the Makefile.

There is a way around this by using a recursive make. In other words, a Makefile that calls itself with different targets or macro definitions. In the following example, if the make is not called with a proper argument or no argument it uses the ``fake'' target .DEFAULT to execute the command given there. For the sake of economy it just recursively calls the make itself with the target help.

If it's given a target of linux, unicos, or aix it then recursively calls itself with the macros CC and LD appropriately set for those platforms.


RM = rm ECHO = echo EXE = mainx SRCS = main.c sub1.c sub2.c sub3.c OBJS = ${SRCS:.c=.o} # do this if given an invalid target .DEFAULT : @$(MAKE) help help : @$(ECHO) "----------------------------------------" @$(ECHO) "do 'make xxx' where xxx=linux|unicos|aix" @$(ECHO) "----------------------------------------" all : $(EXE) ###################################################################### # this only works reliably with GNU ``make'' which correctly handles # MAKE & MFLAGS ###################################################################### linux : $(MAKE) $(MFLAGS) CC=gcc LD=gcc all unicos : $(MAKE) $(MFLAGS) CC=cc LD=segldr all aix : $(MAKE) $(MFLAGS) CC=xlc LD=ld all $(EXE) : $(OBJS) $(LD) -o $@ $(OBJS) $(OBJS) : proj.h clean : -$(RM) -f $(EXE) $(OBJS)
In this example we give an invalid target to exercise the .DEFAULT target, and we use the -s option which is equivalent to adding the .SILENT target to suppress command echoing.
% make -s xxx
----------------------------------------
do 'make xxx' where xxx=linux|unicos|aix
----------------------------------------
Now we try the following, where the option -n says to echo any executed commands, but do not perform them (except for the recursive make if using GNU):
% make -s -n aix
make -sn CC=xlc LD=ld           all
xlc    -c main.c -o main.o
xlc    -c sub1.c -o sub1.o
xlc    -c sub2.c -o sub2.o
xlc    -c sub3.c -o sub3.o
ld -o mainx main.o sub1.o sub2.o sub3.o
Using this technique adds flexibility and allows you to tailor your Makefile for each platform you anticipate using.

As indicated in the Makefile it will reliably run with the GNU make only since there is no real standard regarding the macros MAKE and MAKEFLAGS. The GNU make generally ports well to all common UNIX platforms so obtaining one is not difficult. However, all is not lost if you don't or can't have a GNU make if you use environment variables. The following example shows a passable way. The /bin/env temporarily sets environment variables that are passed on to the executable only.

% env MAKE=/bin/make MFLAGS=-ni /bin/make aix
        /bin/make -ni CC=xlc LD=ld               all
        xlc  -c -o main.o main.c
        xlc  -c -o sub1.o sub1.c
        xlc  -c -o sub2.o sub2.c
        xlc  -c -o sub3.o sub3.c
        ld -o mainx main.o sub1.o sub2.o sub3.o

LeftRight
Slide 7