2015-04-15 2 views
1

Я компилирую большой список файлов в Makefile.

my.list : ${deps} 
    rm -f [email protected] 
    $(foreach F,$^,echo "${F}" >> [email protected];) 

но $ {deps} может быть большим, а сгенерированная командная строка может быть слишком большой для одного вызова SHELL. Можно ли заменить ';' на новую строку '\ n'?

+0

Я предполагаю, что ваша настоящая цель сложнее, чем «эхо» в цикле? Потому что нет причин использовать 'foreach' для этого примера вообще. Вы можете просто 'echo $ ^' напрямую. –

+1

@ EtanReisner, не будет ли это ставить все на одной линии? –

+1

@JonathanWakely Ah, true, 'printf '% s \ n' then. –

ответ

1

Вы можете определить переменную, которая расширяется до конца строки, как так:

define NEWLINE 

endef 

Теперь вы можете использовать $(NEWLINE) расширить до конца строки.

Это ничего не изменит, но foreach по-прежнему будет генерировать одну команду со встроенными символами новой строки между операторами, а не одну команду с ; между операторами.

+0

Будет ли это работать в рецепте создания нескольких строк, которые выполняются как несколько команд оболочки? –

+0

Я не знаю, но тогда я не уверен, что проблема, которую беспокоит ОП, - это все равно. –

+1

Это зависит от того, какова действительная цель вместо 'echo', если это большая командная строка, а список в DEPS' действительно является огромным **, возможно, будет возможно превысить пределы длины для одной командной строки. путь. –

0

Замена ';' по возврату каретки создаст строку того же размера, с той же проблемой.

«foreach» - это просто расширение строки. Если вы хотите выполнить отдельную команду для каждого элемента, вы можете использовать цикл for.

my.list : ${deps} 
    rm -f [email protected] 
    (for F in $^; do echo $$F >> [email protected] ; done) 
+1

Зачем использовать() для запуска подоболочки? Это все равно создаст единую команду оболочки, которая включает в себя весь список 'deps', хотя, по крайней мере, он не будет повторять команду для каждого элемента –

+0

, см. Комментарий Этана Рейснера« если это большая командная строка и список в DEPS действительно огромно, возможно, это может превышать пределы длины одной командной строки таким образом ». – Pierre

+0

Это помогает (запрещает бит подчиненной оболочки), если команда является ограничивающим фактором, а не содержимым самой« DEPS ». –

1

Как уже упоминалось в ответ Джонатана Wakely, в прямолинейный ответ

define newline 


endef 

Интересно, что для всех символов, кроме символа новой строки есть более простой способ получить непечатаемые символы в переменные с некоторой помощью из оболочки, например:

tab := $(shell printf '\011') 

Он не будет работать здесь, хотя, потому что встроенная функция оболочки заменяет все символы новой строки пробелами.

Версия выше все еще немного хрупка, хотя, в частности, при объединении с automake, который тихо удаляет вторую последовательную строку новой строки из входного файла, превращая newline в пустую переменную. Для того, чтобы заставить его сохранить символ новой строки, мы можем расширить сниппет:

blank := 
define newline 

$(blank) 
endef 

Наконец, на самом деле получить отдельную команду оболочки для каждой зависимости, вам нужно запустить сгенерированный строку через eval:

define generate-rule = 
my.list : $(1) 
    rm -f [email protected] 
    $(foreach F,$$^,$(newline)$(tab)echo "${F}" >> [email protected]) 

endef 

$(eval $(call generate-rule,$(deps))) 
0

Редактировать - после некоторых ревизий похоже, что единственная проблема с моим оригиналом была не из-за пробелов, а с MAKE_O. Я исправил его в своей версии, но в основном я удаляю их ниже.

Кстати, было написано оригинальное сообщение, я не уверен, будет ли мое решение релевантным. Тем не менее, я оказался в середине define уже внутри foreach и не мог понять, как вставить новую строку, используя любой из других ответов, как указано.

Решение:

define BR 
$(1) 

endef 

define MAKE_O 
$(1): $(wildcard $(1:obj/%.o=src/%.cpp)); \ 
     $(CXX) ... -c $$< \$(call BR)-o $1 ... \ 
       \$(call BR)&& touch [email protected] 
endef 
$(foreach N,main.o,$(eval $(call MAKE_O,$(N)))) 

Желаемый выход (составление усекается от auto-dependency generation, отсюда и touch):

> make obj/main.o 
g++ ... -c src/main.cpp \ 
-o obj/main.o ... \ 
&& touch obj/main.o 

Я изменил BR выполнить выемку, но оставить конец строки до вы:

define BR 
$(1) 
$(1:%=)  #<remove this comment 
endef 
define MAKE_O 
$(1): $(wildcard $(1:obj/%.o=src/%.cpp)); \ 
     $(CXX) ... -c $$< $(call BR,\)-o $1 ... \ 
       $(call BR,\)&& touch [email protected] 
endef 
$(foreach N,main.o,$(eval $(call MAKE_O,$(N)))) 

Разметка не поможет, чтобы показать это, но линия 2 из BR является $(1:%=_space_)_tab_ Результат (комментарий сам не допускается.):

> make -n obj/main.o 
g++ obj/main.o -c \ 
     -o obj/main.o && \ 
     echo statement on new line 

Я использовал $(call BR,\) так, чтобы новая строка не была распознана как побег новая линия, и $(1:%=пространство)вкладка так, что язычок принуждается (многие аналогичные правила были определены, как SPACE:=$(SPACE) $(SPACE) без предварительного значения.) переменная слева от пробела должны вычисляться то. Чтобы было ясно, удаляя пробелы до и после вызова: ...lastword$(call BR,\)firstword... выходов ...lastword\n\tfirstword... или выписаны,

[^]...lastword \[$] 
[^]$(call BR,\)firstword...[$] 

... урожайности ...

[^]...lastword \[$] 
[^]  firstword...[$] 

для достижения того же (используя^$ для обозначения начала и конца строки. Кто-то еще, вероятно, знает, как форматировать/комментировать это лучше.)

Мой синтаксический ярлык явно не впечатлен «скопированными» круглыми скобками и конечными пробелами, но результат приличный ,

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