2015-01-27 3 views
2

У меня есть простой Makefile:GNU сделать странное поведение

VAR := aaa 
include a.inc 
VAR += bbb 

и a.inc

some_target: $(VAR) 
     @echo "refer to automatic var $^" 
     @echo "refer to VAR $(VAR)" 

aaa: 
bbb: 

и когда я бегу сделать я вижу странную печать:

refer to automatic var aaa 
refer to VAR aaa bbb 

КАЖЕТСЯ что GNU делает замену $ (VAR) в предварительных условиях в момент включения, но $ (VAR) в отладочной печати в какой-то более поздний момент. Это правильное поведение? Почему GNU делает такие действия неинтуитивно?

ответ

2

Это правильно и не является неинтуитивным (хотя, возможно, и не сразу очевидным).

Он работает так же, как переменные на всех других языках.

Попробуйте этот пример оболочки.

$ var=aaa 
$ echo "${var}" 
aaa 
$ ev() { echo "${var}"; } 
$ ev 
aaa 
$ var+=bbb 
$ ev 
aaabbb 

Вы получаете значение переменной, поскольку оно существует в то время, когда вы его используете.

Разница между tgt: prereq и @recipe line в марке - это когда линии оцениваются.

GNU Make Manual об этом говорится в 3.7 How make Reads a Makefile. В частности, для этой ситуации вам нужен последний подкатегорий Rule Definition.

+0

Вы правы. Благодарю. – Andigor

2

Сделать переменные, заданные = (а не :=), разворачиваются, когда они используются.

При запуске make сначала он анализирует файл makefile и определяет цели и предпосылки. В этот момент VAR расширяется до текущего значения.

Затем он запускает первую цель и выполняет рецепт для этой цели, после чего VAR снова расширяется, но к его новому значению.

1

GNU make оценивает makefile за 2 прохода. Все оценивается при первом проходе, кроме рецептов. Рецепты оцениваются со второго прохода. Итак, ваша ссылка на $(VAR) в рецепте some_target оценивается на втором проходе, то есть после добавления += bbb в VAR, который произошел в конце первого прохода.

Для достижения поведения вы хотели вы можете использовать следующую techinique для определения вашего правила:

define rule 
some_target: $(VAR) 
    @echo "refer to automatic var $^" 
    @echo "refer to VAR $(VAR)" 
endef 
$(eval $(rule)) 

Не забывайте использовать вкладки для рецепта линий.

Смежные вопросы