2016-05-17 3 views
2

Я пытаюсь выяснить, является ли следующее поведение ошибкой в ​​Make или намеренно частью дизайна (если это так, я не могу найти его документально в любом месте). Это происходит как с старыми, так и с новыми версиями GNU Make, которые я пробовал.значение просто расширенной переменной через вычисленное имя отличается от рецепта и вне рецепта

Вкратце, поведение состоит в том, что оценка переменных вычисленных имен в рецептах происходит в точке вызова рецепта, а не в месте в файле, где рецепт определен, даже если переменная является просто- расширенный (": =", в отличие от рекурсивно-расширенного "=") (не то, что я ожидаю, что это имеет значение).

Репро код:


a_name := alpha 
b_name := beta 

AB := a 

target1 : $($(AB)_name) 
     echo $^ 
     echo $($(AB)_name) 

alpha : ; 

beta : ; 

AB := b 

target2 : target1 ; 

после вызова make target2

выход я ожидаю:

альфа
альфа

фактический выход:

альфа
бета

ответ

1

Вы должны прочитать 3.7 How make Reads a Makefile, чтобы понять, что вы видите.

Прочитав ее, вы узнаете, что ключевой участок является:

Rule Definition 

A rule is always expanded the same way, regardless of the form: 

immediate : immediate ; deferred 
     deferred 

В этом свете вы видите, что:

target1 : $($(AB)_name) 

в вашем Makefile является сразу расширяется, когда читать в фазе 1. В этот момент определение AB составляет a, поэтому $($(AB)_name) расширяет до $(a_name) , а затем до alpha.

Это alpha тогда, раз и навсегда, предпосылкой к которому $^ будет расширяться, откладывается, в фазе 2, в рецепте, так:

echo $^ 

в рецепте эхо alpha.

В следующей строке в рецепте:

echo $($(AB)_name) 

также расширенный отложенный, в фазе 2, после того, как весь Makefile был прочитан. В этот момент AB обладает своим окончательного определения из фазы 1, который был b, так что здесь $($(AB)_name) расширяется до $(b_name), , а затем к beta. Так что эта линия рецепта отгоняет beta.

+0

Спасибо! Итак, если я правильно понимаю вас, моя гипотеза была неправильной: Это * не *, что вычисляемые переменные, расширенные в рецептах, вычисляются в точке вызова рецепта. Что действительно происходит: все переменные в рецептах принимают значение, которое у них есть в конце make-файла, независимо от того, где находится рецепт. Теперь я смотрю make-файлы по-другому! –