Short answer: you can use environment variables instead of make macros to compute the names, For example, this makefile:
FOO=DEVICE
PLAT_DEVICE=1
!if [set PLAT_DEVICE=$(PLAT_DEVICE)] # add macro to environment
!endif
!if [cmd /c if "%PLAT_$(FOO)%"=="1" exit 1] # do test
!message I am here.
!endif
will give:
>nmake -l
I am here.
Or this variant,
FOO=DEVICE
PLAT_DEVICE=42
!if [set FOO=$(FOO)] && \
[set PLAT_DEVICE=$(PLAT_DEVICE)]
!endif
!if [cmd /c if "%PLAT_$(FOO)%"=="42" exit 1]
!message Test 1a: I am here.
!endif
!if [cmd /c if "%PLAT_%FOO%%"=="42" exit 1]
!message Test 1b: I am here too.
!endif
all:
@ echo Test 2a: %%PLAT_$(FOO)%%
@call echo Test 2b: %%PLAT_%%FOO%%%%
will give:
>nmake -l
Test 1a: I am here.
Test 1b: I am here too.
Test 2a: 42
Test 2b: 42
One major drawback in this answer is that the exporting has to be done explicitly for each make macro. The nmake -l
switch is a just an abbreviation for /nologo
(undocumented?).
Longer answer. The above makefile uses several techniques or tricks. I will try to unravel these in a list of four items.
Item 1: First note nmake
, unlike GNU make, has persistent environment variables (aka variables in nmake). For example,
all: bar
@echo Test 3: %%BAR%%
bar:
@set BAR=Hello World!
gives:
>nmake -l
Test 3: Hello World!
Item 2: You can convert macros to variables, or create a variable, in at least two places:
- in a recipe command line, as shown in Item 1, or
- in a command executed during preprocessing, in square brackets
[...]
.
For example,
AAA = FOO
BBB = BAR
FOO_BAR = This works!
FOO_BAZ = This also works!
!if [set FOO_BAR=$(FOO_BAR)] && \
[set FOO_BAZ=$(FOO_BAZ)] && \
[set CCC=%$(AAA)_$(BBB)%]
!endif
all:
@echo Test 4: %%$(AAA)_$(BBB)%%
@echo Test 5: %%CCC%%
gives:
>nmake -l
Test 4: This works!
Test 5: This works!
>nmake -l BBB=BAZ
Test 4: This also works!
Test 5: This also works!
Two odd points about this. First, it seems each variable must be set with its own command. For example,
!if [set FOO_BAR=$(FOO_BAR) && set FOO_BAZ=$(FOO_BAZ)]
!endif
does not work (I may be missing something obvious here). Second, the &&
connective is almost irrelevant here: it does not short-circuit in nmake, and we are discarding the the result, so probably anything else like +
would work just as well.
Item 3: Item 2 doesn't really illustrate nesting: the nesting shown is a macro within a variable. But true nesting does work. The makefile:
AAA = FOO
BBB = BAR
FOO_BAR = This works!
!if [set AAA=$(AAA)] && \
[set BBB=$(BBB)] && \
[set FOO_BAR=$(FOO_BAR)]
!endif
!if [cmd /c if "%%AAA%_%BBB%%"=="This works!" exit 1]
!message Test 6: I am here
!endif
all:
@call echo Test 7: %%%%AAA%%_%%BBB%%%%
will give:
>nmake -l
Test 6: I am here
Test 7: This works!
In the recipe, the call
seems to be needed simulate delayed expansion; see Stephan's answer to Variables are not behaving as expected. It is not needed in the Test 6, =="This works!"
test.
Item 4: The preprocessing tests shown in:
!if [cmd /c if "%PLAT_$(FOO)%"=="42" exit 1]
!message Test 1a: I am here.
!endif
!if [cmd /c if "%PLAT_%FOO%%"=="42" exit 1]
!message Test 1b: I am here too.
!endif
are similar to the Unix test
command, except here TRUE=1.