5

Возможно ли иметь переменные в GNU Make recipes?

Что-то вроде этого не работает:

%_t.mkd : %.mkd
    REV=$$(svn info $<|grep 'Last Changed Rev'|cut -f4 -d\ )
    echo $${REV}

Есть ли какой-нибудь способ заставить это работать вообще?

Как видите, я хочу извлечь ревизию изменения файла, а затем использовать ее позже в полном рецепте. К сожалению, я не могу использовать svn:keywords как мне нужен номер редакции вне рассматриваемого документа.

4 ответа4

6

Это не работает, потому что инструмент make запускает новый процесс оболочки для каждой строки рецепта. А переменные оболочки - даже "экспортированные" переменные среды - не могут распространяться "вверх"; они исчезают, как только завершается процесс оболочки.

  • Традиционный метод заключается в соединении строк рецепта с помощью \ в Makefile:

    foo: bar baz
        line1; \
        line2; \
        line3
    

    (Обратите внимание, что команды должны быть разделены с помощью ; или && , поскольку обратные слеши также передаются оболочке, которая выполняет то же соединение строк).

    Смотрите также info make "Splitting Lines" и info make "Splitting Recipe Lines" в руководстве по GNU Make.

  • Другой метод - make всегда использовать один процесс оболочки для всего рецепта, используя .ONESHELL :

    .ONESHELL:
    
    foo: bar baz
        line1
        line2
        line3
    

    Смотрите info make "One Shell".

    (Обратите внимание, что пока .ONESHELL рекомендует ONESHELL , не все версии make поддерживают его ; Например, BSD make имеет только флаг командной строки. Это не должно быть проблемой, хотя.)

4

Благодаря https://stackoverflow.com/questions/6519234/cant-assign-variable-inside-recipe

Это решение для изменения переменной в рецепте:

recipe: 
        $(eval variablename=whatever)
1

Согласно Gnu Make 6.5 Настройка переменных:

Оператор присваивания оболочки != может использоваться для выполнения программы и установки переменной для ее вывода. Этот оператор сначала оценивает правую часть, а затем передает этот результат в оболочку для выполнения. Если результат выполнения заканчивается новой строкой, эта новая строка удаляется; все остальные символы новой строки заменяются пробелами. Полученная строка затем помещается в именованную рекурсивно-расширенную переменную.

Таким образом, вы можете попробовать следующее (не проверено):

REV != $$(svn info $<|grep 'Last Changed Rev'|cut -f4 -d\ ) \
echo $${REV}
0

взяв то, что упомянул @ user3645902, вот решение основного вопроса:

recipe:
    @$(eval REV=`svn info $<|grep 'Last Changed Rev'|cut -f4 -d`)
    @echo $(REV)

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .