2017-02-02 1 views
-1

Я пытаюсь построить GNU Make Canned Recipe, например, так:Почему я не могу создавать переменные в ГНУ сделать «определение» директива

define this-will-fail 
my_var=1 
$(info your variable is $(my_var)) 
endef 

$(this-will-fail) 

Это приводит к ошибке *** missing separator. Stop.

Однако, следующие работы, как и ожидалось:

define why-does-this-work 
$(eval my_var=1) 
$(info your variable is $(my_var)) 
endef 

$(why-does-this-work) 

печатая your variable is 1.

Я смотрю AOSP's build system и часто вижу использование eval в паре с define. Какова связь между этими двумя элементами и почему я не могу создавать переменные «нормально» при использовании define?

+0

консервированный рецепт документации, вы ссылаетесь на переговоры о _shell_ фрагменты, а не Make (фактически, само слово «рецепт» в контексте Make всегда означает «часть кода оболочки правила»). –

+0

@MichaelLivshin спасибо, это был лакомый кусочек, мне нужно было очистить все мое замешательство. Если вы хотите опубликовать его как «ответ», я буду рад принять – Hamy

ответ

0

Ответ основан на простой точке с большими разветвлениями - в файле makefile есть два диалекта, 1) сам язык создания и 2) язык оболочки, который вы используете для таких вещей, как вызов gcc.

Напоминания о нормальном макияже «правила» Синтаксис:

targets : prerequisites 
     recipe 

Пока цель марки и предпосылка находятся в сделать синтаксис, материал в рецепте есть в синтаксисе оболочки , не делает синтаксис ,

Это объясняет, почему вы не можете делать такие вещи, как правопреемник сделать переменные как часть рецепта, как это:

all: the_dependencies_of_all 
    this_will_not_work := because_the_shell_does_not_know_what_this_line_means 

В синтаксисе оболочки бит, сделать это три специальные текстовые манипуляции, а затем оставшаяся строка передан дословно в оболочку. Эти три шага

  1. сделка с сбежавших переносом строк (например, обратный слеш с последующим новой строкой)
  2. запустить любую марку функция (как $(filter ....) и $(eval ..)
  3. расширить любой сделать целевую переменные (как [email protected])

В нормальном случае эти процессы с тремя шагами, а затем оболочками происходят один раз на линию рецепта, поэтому каждая строка вашего рецепта makefile запускается в другой оболочке (следовательно, некоторые вызовы make порождают множество /bin/sh).

Манипуляция # 2 выше объясняет, почему вы можете использовать eval внутри рецепта, чтобы добавить синтаксис make к вашему рецепту. Eval превратится в пустую строку, которая не вызовет проблем с оболочкой, но make будет оценивать строку внутри вашего оператора, поэтому возможны такие вещи, как определения переменных.

Точный момент, когда эта оценка происходит, немного сложна, чтобы ее можно было сбрасывать - кажется, это происходит, когда переменная сначала расширяется, что само зависит от того, где вы ссылаетесь на эту переменную в своем файле.Возможно, кто-то может прояснить это немного больше, так как, когда это происходит уже последствия для призываний марки, которые используют -j флаг для запуска нескольких линий рецепта параллельно

Дополнительная информация:

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