arinmorf
arinmorf

Reputation: 1394

Makefile- How to define variables in a target that creates other targets?

I don't fully understand how to use target-specific variables to act as targets themselves, having their own dependencies and recipes.

Example Makefile that works but does not use target-specific variables:

VAR=progName
ATARGET: $(VAR)
    @echo Do actions for $@ based on the completed target $(VAR)
$(VAR):
    @echo Do actions on $@

make ATARGET

Do actions on progName

Do actions for ATARGET based on the completed target progName

Makefile which does NOT work trying to use target-specific variables (note the lack of "Do actions on progName" when executing make):

ATARGET:VAR=progName
ATARGET: $(VAR)
    @echo Do actions for $@ based on the completed target $(VAR)
$(VAR):
    @echo Do actions on $@

make ATARGET

Do actions for ATARGET based on the completed target progName

Desired Makefile behavior:

ATARGET:VAR=progName
ATARGET: $(VAR)
    @echo Do actions for $@ based on the completed target $(VAR)

BTARGET:VAR=otherProgName
BTARGET: $(VAR)
    @echo Do actions for $@ based on the completed target $(VAR)

$(VAR):
    @echo Do actions on $@

make ATARGET

Do actions on progName

Do actions for ATARGET based on the completed target progName

make BTARGET

Do actions on otherProgName

Do actions for BTARGET based on the completed target otherProgName

These are simple Makefiles to illustrate the problem- the actual makefile has several targets depending on the value of VAR.

PGM = $(VAR)_test.exe;
LIB = lib$(VAR).a;
LIBLINKNAME = $(VAR);

Upvotes: 1

Views: 1226

Answers (1)

Wintermute
Wintermute

Reputation: 44063

You cannot change the value of make variables depending on the target you're building; they are processed before all that. You can, however, have rules with multiple targets and produce your desired behavior with them. For example:

VAR = progName otherProgName

ATARGET: progName
    echo Do actions for $@ based on the completed target $<

BTARGET: otherProgName
    echo Do actions for $@ based on the completed target $<

$(VAR):
    echo Do actions on $@

VAR is now no longer a terribly good name (perhaps better to call it LIST or something). This way, the same recipe applies for the progName and otherProgName targets, and which one is generated depends on the prerequisites of the target you're building.

In conjunction with string-handling functions, this is adaptable for more complex use cases. For example, you could use

# pattern substitution: append _test.exe to all entries in VAR
PGM = $(VAR:%=%_test.exe)

$(PGM):
    recipe for individual *_test.exe programs here.

You may also be very interested in static pattern rules.

Upvotes: 2

Related Questions