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.
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.
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)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 xxx ---------------------------------------- do 'make xxx' where xxx=linux|unicos|aix ----------------------------------------Using this technique adds flexibility and allows you to tailor your Makefile for each platform you anticipate using.% 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.oAs 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