Краткий ответ: вы можете использовать переменные окружения вместо макроса make для вычисления имен. Например, этот make-файл:
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
(недокументированное?).
Более длинный ответ. Приведенный выше make-файл использует несколько приемов или приемов. Я попытаюсь распутать их в списке из четырех предметов.
Элемент 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 на самом деле не иллюстрирует вложенность: показанная вложенность является макросом внутри переменной. Но истинное вложение работает. 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%%%%
даст:
>nmake -l
Test 6: I am here
Test 7: This works!
В рецепте call
кажется необходимым для имитации отложенного расширения; см. ответ Стефана на Переменные работают не так, как ожидалось . Не требуется в тесте Test 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.