Makefile назначает вывод команды переменной - программирование
Подтвердить что ты не робот

Makefile назначает вывод команды переменной

У меня есть script, который сжимает мои файлы 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

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

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

Выходы:

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

Ответ 1

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

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

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

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

all:
    @echo "Compiling CSS"
    php minify_css.php

Ответ 2

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

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

Как описано, проблема сводится к выполнению команды $(shell). Он выполняется, когда переменные make файла оцениваются, что до того, как какая-либо из целей была разрешена или обработана. Чтобы обойти это, вы можете разбить команду $(shell), чтобы произойти в отдельном вызове 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)

Описание

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

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

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

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

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

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

Сопутствующие соображения

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