GNU Make程序证明了computed names的功能。我必须使用Microsoft nmake程序,并且需要检查宏是否具有指定的值或至少已定义。
makefile定义了一个值为FOO
的宏DEVICE
。此外,宏PLAT_DEVICE
可以定义为值1
。在GNU make语法中,您可以使用
FOO=DEVICE
PLAT_DEVICE=1
!if "$(PLAT_$(FOO))" == "1"
!message I am here.
!endif
宏FOO
的值定义在此处检查其他哪个宏。不幸的是,nmake不了解这一点。条件始终评估为false,永远不会显示该消息。
如何使用nmake实施此操作?
答案 0 :(得分:0)
编辑:这是我的第一个答案,没有那么有用。请参阅我关于使用环境变量的第二个答案。
不幸的是,NMAKE没有GNU Make中的计算变量名。
但是确实允许从其他宏构造宏名称:请参见https://docs.microsoft.com/en-us/cpp/build/defining-an-nmake-macro?view=vs-2017。
因此,根据您的具体情况,以下解决方法可能会起作用:
DEVICE = 1
PLAT_DEVICE_$(DEVICE) =
!ifdef PLAT_DEVICE_1
!message I am here.
!endif
或者,作为这个想法的一个小变化:
DEVICE = 1
PLAT_DEVICE_$(DEVICE) = plat_device
!if "plat_device" == "$(PLAT_DEVICE_1)"
!message I am here.
!endif
答案 1 :(得分:0)
简短答案:您可以使用环境变量代替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:与GNU make不同,第一笔记nmake
具有持久的环境变量(nmake中的变量)。例如,
all: bar
@echo Test 3: %%BAR%%
bar:
@set BAR=Hello World!
给予:
>nmake -l
Test 3: Hello World!
项目2::您可以在至少两个位置将宏转换为变量,或创建变量:
[...]
中。例如,
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。