Makefile назначает вывод команды переменной - PullRequest
18 голосов
/ 31 января 2012

У меня есть скрипт, который сжимает мои css-файлы и выводит имя файла выходного файла.
Я пытаюсь создать make-файл для автоматизации процесса:

all:
    @echo "Compiling CSS"
    CSS_OUTPUT=$(shell php minify_css.php )
    echo $(CSS_OUTPUT)

Я пытаюсьсохранить имя выходного файла в переменной CSS_OUTPUT, но я делаю что-то не так, так как весь этот make-файл просто печатает:

$ make
abcdefg.css
Compiling CSS
CSS_OUTPUT=
echo 

Таким образом, вывод не назначен CSS_OUTPUT.Кроме того, почему вывод php печатается до @echo "Compiling CSS"?

Я пробовал с этим:

all:
    @echo "Compiling CSS"
    CSS_OUTPUT=$(shell echo php minify_css.php )
    echo $(CSS_OUTPUT)

Но это только ухудшается:

$ make
Compiling CSS
CSS_OUTPUT=php minify_css.php
./minify_css.php: line 1: ?php: No such file or directory
./minify_css.php: line 3: syntax error near unexpected token `dirname'
./minify_css.php: line 3: `require_once( dirname(__FILE__) . DIRECTORY_SEPARATOR . 'maintenance.php' );'
make: *** [css] Error 2

Редактировать После ответа, предоставленного в комментариях, который предлагает использовать eval:

@echo "Compiling CSS"
$(eval CSS_OUTPUT:=$(shell php minify_css.php))
echo ${CSS_OUTPUT}

Выходы:

make: *** No targets specified and no makefile found.  Stop.

Ответы [ 2 ]

11 голосов
/ 31 января 2012

Сделать работы в два этапа. Во-первых, он читает в make-файле, оценивает переменные и строит граф зависимостей. Функции Make также оцениваются на этом этапе. На втором этапе он выполняет необходимые рецепты для обновления основной цели. Это означает, что вызов функции $(shell ...) расширяется на первом этапе, прежде чем будет запущен какой-либо рецепт. Вывод команды заменяет вызов функции оболочки, но я подозреваю, что вывод команды php не переходит в STDOUT, поэтому вместо того, чтобы заканчиваться на CSS_OUTPUT=abcdefg.css (что было бы тем, что вы хотите), abcdefg.css отображается на экране, и результат функции оболочки пуст.

Далее рецепт выполняется, но когда это делается, каждая строка запускается в отдельном экземпляре оболочки, поэтому команды на разных строках в рецепте не имеют доступа к переменным оболочки, установленным в другой строке (что было бы бесполезно в этот случай в любом случае, из-за предыдущего вопроса). Один из способов противостоять этому - склеить строки, оканчивая их точкой с запятой и обратной косой чертой. Теперь они выполняются как одна строка в одном экземпляре оболочки.

Другая проблема заключается в том, что в последней строке рецепта вы ссылаетесь не на переменную оболочки (которая и есть CSS_OUTPUT), а на переменную makefile, которая никогда не была установлена.

Есть ли причина, по которой вы просто не делаете это так:

all:
    @echo "Compiling CSS"
    php minify_css.php
3 голосов
/ 28 января 2014

Проблема и решение

Я сам столкнулся с той же проблемой. Я нашел способ обойти это, но это определенно не идеально.

Как описано, проблема сводится к тому, когда выполняется команда $(shell). Он выполняется, когда оцениваются переменные make-файла, то есть до того, как любая из целей была решена или обработана. Чтобы обойти это, вы можете отключить команду $(shell) для отдельного вызова make-файла. Чтобы запутаться, я просто создал «скрытую» цель для всей моей работы по созданию постфайла в одном и том же файле и сделал рекурсивный вызов make для моего же make-файла. Результат выглядит примерно так:

override MY_MAKEFILE:=$(MAKEFILE_LIST)
override MY_MAKE_INVOCATION_CMD_LINE:=$(MAKE) -C $(CURDIR) $(if $(MY_MAKEFILE),-f $(MY_MAKEFILE),) --no-print-directory

all: minify_css.php
    @echo "Compiling CSS"
    @$(MY_MAKE_INVOCATION_CMD_LINE) all_hid

minify_css.php:
    <create the minify_css.php file here>    

all_hid:
    @$(MY_MAKE_INVOCATION_CMD_LINE) print_css_hid CSS_OUTPUT=$(shell php minify_css.php )

print_css_hid :
    echo $(CSS_OUTPUT)

Объяснение

Команды переопределения

Первая строка этой команды принудительно устанавливает переменную, которая не может быть переопределена из командной строки для сбора имени make-файла. Первая строка ДОЛЖНА называться абсолютной первой строкой в ​​вашем make-файле, поскольку включение других make-файлов может изменить это, и оно не работает изнутри включенных make-файлов. Следует отметить тот факт, что это будет пустым, если вы не указали make-файл в командной строке, что должно означать, что он может быть вызван таким же образом, когда вызывается из make-файла.

Вторая строка просто создает вызов make-файла, устанавливая некоторые параметры по умолчанию, такие как изменение текущего каталога, из которого была вызвана командная строка make-файла, и включающего только спецификацию make-файла для использования, если он был включен в исходный файл. звоните.

Обратите внимание, что эти первые две строки в настоящее время реализованы в моей системе сборки, поэтому они действительно работают для нескольких вложенных рекурсивных вызовов одного и того же файла сборки.

Рекурсивный вызов

Следующие две строки являются важными, отвечающими на ваш исходный запрос. Чтобы продемонстрировать создание файла, а не просто использование возврата команды оболочки, я притворился, что вашему файлу также необходимо создать файл minify_css.php. Когда я делаю рекурсивный вызов make-файла для цели all_hid, я знаю, что цель all оценивается. Это означает, что зависимость minify_css.php уже обработана, поэтому я могу гарантировать, что она уже существует, что позволяет оценивать команду $(shell php minify_css.php) при первом рекурсивном обращении к make-файлу и работать с созданным файлом. Следующим шагом было собрать значение CSS_OUTPUT и передать его в другой рекурсивный вызов. Чтобы сделать это, я снова вызвал make-файл рекурсивно из уже рекурсивного вызова и передал его в командной строке. Помните, что во время вызова make-файла в под-марках доступны только те переменные, которые вы явно экспортировали, поэтому мы не можем просто установить его, а затем сделать рекурсивный вызов на следующей строке, он должен фактически передаваться как часть команды -линия. В рекурсивном make-файле следующего уровня, когда мы вызываем цель print_css_hid, переменная будет установлена ​​в командной строке и может использоваться.

Подкомпоненты

В этом случае вы на самом деле рекурсивно вызываете свой собственный make-файл, поэтому нужно учитывать, что все остальные переменные установлены неправильно. К счастью, этого не происходит. Любые значения командной строки для параметров, передаваемых исходной командной строке, автоматически передаются при каждом вызове make, вызываемом из файла. Поскольку единственными источниками ввода, которые могут повлиять на построение ваших переменных в make-файле, является содержимое каталогов, с которыми вы работаете, параметры командной строки, каталог, из которого был вызван make-файл, и параметры в самом make-файле, у вас просто есть чтобы убедиться, что вы не делаете что-то вроде случайного включения вновь созданного файла в список «источников» во время вложенных вызовов, и вы можете гарантировать, что среда будет настроена так же.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...