计算的宏名称

时间:2019-01-07 12:31:41

标签: nmake

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实施此操作?

2 个答案:

答案 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::您可以在至少两个位置将宏转换为变量,或创建变量:

  • 在配方命令行中(如第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 answerVariables 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。