Search code examples
makefilegnu-make

How to optimize this makefile?


I'm trying to optimize this makefile for adding PGM.

I created makefile needs to be optimized:

SOURCES = main.cpp logic.cpp
OBJECTS = $(SOURCES:.cpp=.o)
CC = CC
MODEL001 = FLAGA FLAGB
MODEL002 = FLAGC
CFLAGS001 = -c $(MODEL001:%=-D%)
CFLAGS002 = -c $(MODEL002:%=-D%)
PGMNUM = 001 002

all: PGM001 PGM002

PGM001:$(SOURCES)
    $(CC) $(CFLAGS001) $(SOURCES)
    $(CC) -o $PGM001 $(OBJECTS)

PGM002:$(SOURCES)
    $(CC) $(CFLAGS002) $(SOURCES)
    $(CC) -o $PGM002 $(OBJECTS)

Currently, I change the following variables when adding a PGM003.

ADD : MODEL003, CFLAGS003, PGM003:$(SOURCES)...
MODIFY : PGMNUM, all

Just by adding MODEL003 and PGMNUM, this makefile seems to work. How can I do it?

(pseudo code like this but does not work):

SOURCES = main.cpp logic.cpp
OBJECTS = $(SOURCES:.cpp=.o)
CC = CC
MODEL001 = FLAGA FLAGB
MODEL002 = FLAGC
MODEL003 = FLAGD FLAGE

PGMNUM = 001 002 003

CFLAGS$(PGMNUM) = -c $(MODEL$(PGMNUM):%=-D%)

all: $(PGMNUM:%=PGM%)

PGM$(PGMNUM):$(SOURCES)
    $(CC) $(CFLAGS$(PGMNUM)) $(SOURCES)
    $(CC) -o $PGM$(PGMNUM) $(OBJECTS)


Solution

  • By 'optimize', I take it you want to make it use less lines of code, rather than make it run faster. If so, you can use a function and eval as so:

    SOURCES := main.cpp logic.cpp
    PGMNUMS := 001 002 003
    CC := CC
    
    MODEL001 := FLAGA FLAGB
    MODEL002 := FLAGC
    MODEL003 := FLAGD
    
    define func
    
    CFLAGS$1 := -c $(MODEL$(p):%=-D%)
    OBJECTS$1 := $$(SOURCES:.cpp=.$1.o)
    
    $$(OBJECTS$1) : %.$1.o : %.cpp
            $(CC) $$(CFLAGS$1) -o $$@ $$^
    
    PGM$1 : $$(OBJECTS$1)
            $(CC) -o $$@ $$^
    
    endef
    
    
    $(info --vv--  show generated code --vv--)
    $(foreach p,$(PGMNUMS),$(info $(call func,$p)))
    $(info --^^-- end of generated code --^^--)
    
    #actually generate the calls:
    $(foreach p,$(PGMNUMS),$(eval $(call func,$p)))
    
    all: $(PGMNUM:%=PGM%)
    

    Basically, you define a function func, and then run it for all values of $(PGMNUMS). Notice the use of $$ in the function definition -- in the function, $1 will expand to the first parameter. Items with $$var in front of them will expand to $var, rather than expanding at the time. I added a $(info..) which is useful to debug what you generate.