В моем GNUmakefile я хотел бы иметь правило, которое использует временный каталог. Например:
out.tar: TMP := $(shell mktemp -d)
echo hi $(TMP)/hi.txt
tar -C $(TMP) cf $@ .
rm -rf $(TMP)
Как написано выше, указанное выше правило создает временный каталог во время его анализа . Это означает, что, даже если я не разглядываю .tar все время, создается много временных каталогов. Я бы хотел, чтобы мой / tmp был завален неиспользуемыми временными каталогами.
Есть ли способ заставить переменную быть определенной только при запуске правила, а не всякий раз, когда оно определено?
Моя основная мысль - сбросить mktemp и tar в сценарий оболочки, но это выглядит несколько неприглядно.
$(eval $@_TMP := $(shell mktemp -d))
произойдет, когда Makefile будет сначала оценен не в порядке процедур правил. Другими словами,$(eval ...)
происходит раньше, чем вы думаете. Хотя это может быть хорошо для этого примера, этот метод вызовет проблемы для некоторых последовательных операций.Относительно простой способ сделать это - написать всю последовательность в виде сценария оболочки.
Я объединил некоторые связанные советы здесь: https://stackoverflow.com/a/29085684/86967
источник
@
иeval
и делать ту же работу). Обратите внимание, что в выводе вы видите$TMP
(напримерtar -C $TMP ...
), хотя значение правильно передается команде.SHELL := /bin/bash
можете включить в свой make-файл функции, специфичные для BASH.Другая возможность - использовать отдельные строки для установки переменных Make при запуске правила.
Например, вот make-файл с двумя правилами. Если правило срабатывает, оно создает временный каталог и устанавливает для TMP имя временного каталога.
Запуск кода дает ожидаемый результат:
источник
ruleA: TMP = $(shell mktemp -d testruleA_XXXX)
иruleB: TMP = $(shell mktemp -d testruleB_XXXX)
произойдет при первой оценке Makefile. Другими словами,ruleA: TMP = $(shell ...
происходит раньше, чем вы думаете. Хотя это может работать в данном конкретном случае, этот метод вызовет проблемы для некоторых последовательных операций.Мне не нравятся ответы «Не», но ... нет.
make
Переменные являются глобальными и должны оцениваться на этапе «синтаксического анализа» make-файла, а не на этапе выполнения.В этом случае, пока переменная локальна для одной цели, следуйте ответу @ nobar и сделайте ее переменной оболочки.
Целевые переменные также считаются вредными для других реализаций make: kati , Mozilla pymake . Из-за них цель может быть построена по-разному, в зависимости от того, является ли она построенной автономно, или как зависимость родительской цели с переменной, специфичной для цели. И вы не будете знать, как это было , потому что вы не знаете, что уже построено.
источник