Вопрос: Переменные в GNU Сделать рецепты, возможно ли это?


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

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

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

Есть ли способ сделать эту работу вообще?

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


4
2017-07-31 06:49


Источник




Ответы:


Это не работает, потому что 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 рекомендуется POSIX, не все версии поддерживают его; например BSD имеет только флаг командной строки для него. Это не должно быть проблемой.)


6
2017-07-31 07:56





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

Это решение изменить переменную в рецепте:

recipe: 
        $(eval variablename=whatever)

3
2017-10-11 19:54





В соответствии с Gnu Make 6.5 Установка переменных:

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

Поэтому вы можете попробовать следующее (не проверено):

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

1
2017-07-31 07:56



Это будет работать на верхнем уровне make-файла, но не в середине рецепта (где используется синтаксис оболочки, а не синтаксис Make). Это было бы REV != svn info ... слишком. - grawity
Возможно, op может установить переменную один раз на верхнем уровне своего файла makefile? : / - DavidPostill♦
Нет, как вы видите, мне нужно это как часть рецепта, так как значение будет отличаться для разных файлов. - Magnus


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

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

0
2018-01-15 15:15