Вопрос или проблема
Я пытаюсь использовать makefile для объединения сочетания команд, которые должны выполняться одна за другой. Часть makefile выглядит следующим образом:
.PHONY: dispersion
all: dispersion
-include make.in
dispersion:
phonopy --qe -d --dim='$(nx) $(ny) $(nz)' -c $(material)_primitive.in
$(eval VAR=$(shell grep nat supercell.in))
echo $(VAR)
По сути, первая строка создает файл с именем “supercell.in”, а вторая создает переменную с именем VAR, которая будет использоваться в последующих строках. Вышеуказанное не присваивает значение переменной, и я предполагаю, что это связано с приоритетом выполнения строк. Я был бы признателен за способ решения этой проблемы.
Попробуйте использовать оператор обратных кавычек для выполнения команды.
.PHONY: dispersion
all: dispersion
-include make.in
dispersion:
phonopy --qe -d --dim='$(nx) $(ny) $(nz)' -c $(material)_primitive.in
$(eval VAR=`grep nat supercell.in`)
echo $(VAR)
Я полагаю, что проблема связана с тем, когда $(shell)
оценивается интерпретатором.
Ответ или решение
Ваша проблема связана с тем, что команда $(eval VAR=$(shell ...))
выполняется на этапе разбора Makefile, а не во время выполнения цели. В результате переменная VAR
не будет иметь значение, которое вы ожидаете.
Чтобы правильно назначить переменную на основе результата выполнения команды, вы можете использовать $(shell ...)
в самом правиле или непосредственно внутри команды. Таким образом, результатами выполнения команды будет являться переменная, которую вы сможете использовать позже.
Вот как можно изменить ваш Makefile:
.PHONY: dispersion
all: dispersion
-include make.in
dispersion:
phonopy --qe -d --dim='$(nx) $(ny) $(nz)' -c $(material)_primitive.in
VAR=$(shell grep nat supercell.in)
echo $$VAR
Обратите внимание, что вместо $(eval ...)
мы просто создаем переменную VAR
и присваиваем ей результат команды grep
. Также при выводе значения переменной необходимо использовать двойной символ доллара ($$
), чтобы указать make, что вы хотите использовать значение переменной, а не создать новую переменную.
Этот подход позволяет вам использовать результат выполнения команды grep nat supercell.in
в следующей строке в рамках одной цели. Таким образом, вы получите значение переменной VAR
, присвоенное непосредственно в процессе выполнения команды.
Если вам всё же нужно использовать значение VAR
в нескольких местах в вашем Makefile, вы можете применить следующий подход:
.PHONY: dispersion
all: dispersion
-include make.in
dispersion:
phonopy --qe -d --dim='$(nx) $(ny) $(nz)' -c $(material)_primitive.in
@VAR=$(shell grep nat supercell.in); \
echo $$VAR; \
# здесь вы можете продолжить использовать $$VAR в других командах
В этом примере используется @
перед командой для предотвращения вывода самой команды в терминал (выводится только результат), а VAR
будет доступен в рамках этой последовательности команд благодаря продолжению в том же контексте.
Надеюсь, это поможет вам правильно определить переменную на основе результата выполнения команды в вашем Makefile.