简答:您可以使用环境变量代替make宏来计算名称,例如,这个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
将给予:
>nmake -l
I am here.
或者这个变种,
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%%%%
将给予:
>nmake -l
Test 1a: I am here.
Test 1b: I am here too.
Test 2a: 42
Test 2b: 42
这个答案的一个主要缺点是必须为每个 make 宏显式地完成导出。 nmake -l 开关只是 /nologo 的缩写(未记录?)。
更长的答案。 上面的 makefile 使用了几种技术或技巧。我将尝试在包含四个项目的列表中解开这些内容。
第 1 项: 第一个注释 nmake 与 GNU make 不同,它具有持久性环境变量(在 nmake 中也称为 变量)。例如,
all: bar
@echo Test 3: %%BAR%%
bar:
@set BAR=Hello World!
给予:
>nmake -l
Test 3: Hello World!
第 2 项:您可以将宏转换为变量,或创建变量,至少在两个地方:
- 在配方命令行中,如第 1 项所示,或
- 在预处理期间执行的命令中,方括号
[...]。
例如,
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%%
给予:
>nmake -l
Test 4: This works!
Test 5: This works!
>nmake -l BBB=BAZ
Test 4: This also works!
Test 5: This also works!
关于这个有两个奇怪的地方。首先,似乎每个变量都必须使用自己的命令进行设置。例如,
!if [set FOO_BAR=$(FOO_BAR) && set FOO_BAZ=$(FOO_BAZ)]
!endif
不起作用(我可能在这里遗漏了一些明显的东西)。其次,&& 连接词在这里几乎是无关紧要的:它不会在 nmake 中短路,我们会丢弃结果,所以可能像 + 这样的其他任何东西也可以正常工作。
第 3 项: 第 2 项并没有真正说明嵌套:显示的嵌套是变量中的宏。但真正的嵌套确实有效。生成文件:
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%%%%
将给予:
>nmake -l
Test 6: I am here
Test 7: This works!
在配方中,call 似乎需要模拟延迟扩展;见Stephan's answer 至Variables are not behaving as expected。测试 6 中不需要它,=="This works!" 测试。
第4项:预处理测试如下:
!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
类似于 Unix 的 test 命令,除了这里的 TRUE=1。