2015-04-22 2 views
1

Я пытаюсь сделать вывод из многострочной директивы GNU make, и я не могу. Пример:Многострочное определение в GNU make

define A 
1 
2 
endef 
all: 
    @echo W=$(word 1,$(A)) 

Запуск make дает результат, я ожидал, как минимум:

W=1 
make: 2: Command not found 
make: *** [all] Error 127 

Вероятно, что часть $(A) пролил за пределы функции $(word).

Это ошибка или предполагаемое поведение? Если «разлив» преднамерен, как он работает?

P.S. GNU make v3.81 на Linux/x64

ответ

2

Функция $(word) разделяется на пробелы. Не пробелы, пробелы.

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

Добавить временное пространство на линии 1 или ведущее место на линии 2, и вы получите ожидаемое поведение.

Это согласуется с GNU make 3.81, 3.82, 4.0 и 4.1 в некоторых быстрых тестах здесь.

Причина, по которой вы видите «разлив», как вы ее назвали, объясняется тем, как определяется определение. Он расширяется буквально, newline и все. (Думайте о расширении шаблона.)

Таким образом, make расширяет определение в вызове до $(word 1,...), а затем расширяет этот результат (целое определение, включая новую строку), в шаблон рецепта и заканчивается двумя строками, которые он выполняет в качестве рецепта.

Рассмотрим макрос так:

define somecommands 
echo foo 
echo bar 
echo baz 
endef 

all: 
    $(somecommands) 

Что бы ожидать, чтобы это произошло здесь? Сколько строк является телом all? Сколько снарядов работает здесь? Какие команды выполняются? Ответ - три строки, три оболочки и три команды эха.

Если новые строки не были подсчитаны, то вы бы эффективно работать echo foo echo bar echo baz в одной команде и получить foo echo bar echo baz в качестве выходного сигнала вместо ожидаемого (и гораздо более полезным) foo, bar и baz на трех различных линиях.

+0

Я не спрашивая о '$ (word)' функции. Я прошу объяснить сообщение об ошибке «make: 2: Command not found». Меня интересует, как/почему «2» появился вне функции и попал в конвейер выполнения make. Это вопрос, который я задал. – Dummy00001

+0

Вы спрашивали о том, как «часть' $ (A) 'разлилась вне функции $ (word)". Я просто ответил на этот вопрос ... хотя теперь я вижу, как ответ не полностью объяснен в том, что я написал (хотя он есть). Оставайтесь на линии. –

+0

Нет. На самом деле это не ответ. Это в основном экстраполяция официальной (неопределенной по предметной) документации, которая вообще не затрагивает двусмысленность. Я начинаю думать, что это просто ошибка в реализации многострочных определений. Например, попробуйте добавить точку с запятой в конце команды 'echo' и посмотреть, как изменяется сообщение об ошибке. (Если под Linux, запустите с помощью 'strace -ff -e execve', чтобы увидеть всю бессмыслицу во всей красе.) – Dummy00001

4

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

В вашем примере, перед запуском чего-либо сделать расширяет @echo W=$(word 1,$(A)).

  1. $(A) становится 1¶2 (не знаю, что это выглядит как в вашем браузере, но я использую представлять символ новой строки)
  2. Теперь 1¶2 это одно слово, насколько сделать обеспокоен, так $(word 1,1¶2) естественно расширяется до 1¶2 (вы можете увидеть, где это происходит еще?)
  3. Это оставляет сделать строкой @echo W=1¶2. Сделайте добросовестно прохождение первой строки этого в оболочку (без @, так как это специальное значение для сделать). Оболочка выполняет echo W=1.
  4. выполняет 2 в оболочка.
  5. Вторая оболочка жалуется, что не может найти команду 2.

Итак, да, ожидаемое поведение.

[Предупреждение: небольшое упрощение выше, где я замазать биту, где сделать способно игнорировать оболочку и вызвать команду себя, если строка не имеет оболочек метасимволов в нем]

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