2015-04-15 74 views
1

我正在編譯Makefile中的大量文件列表。

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

但是$ {deps}可能很大,並且生成的命令行對於一個SHELL調用可能太大。是否可以用換行符'\ n'替換​​3210?

+0

我假設你的真實目標比loop中的echo更復雜?因爲沒有理由在這個例子中使用'foreach'。你可以直接'echo $ ^'。 –

+1

@EtanReisner,不會把所有東西都放在一條線上嗎? –

+1

@JonathanWakely啊,真的,'printf'%s \ n'那麼。 –

回答

1

您可以定義擴展到一個新行,像這樣的變量:

define NEWLINE 

endef 

現在你可以使用$(NEWLINE)拓展到一個新行。

雖然這不會改變任何東西,但foreach仍然會在語句之間生成一個帶有嵌入換行符的單個命令,而不是在語句之​​間帶有;的單個命令。

+0

這是否會在配方中創建多條作爲多個shell命令運行的行? –

+0

我不知道,但後來我不確定OP所擔心的問題是否真的值得關注。 –

+1

這取決於真正的目標是什麼,而不是'echo',如果它是一個大的命令行,並且'DEPS'中的列表真的是**巨大**它可能超過單個命令行的長度限制this辦法。 –

0

替換';'通過回車將產生一個相同大小的字符串,並受同樣的問題影響。

「foreach」只是一個字符串擴展。如果你想爲每個項目執行一個單獨的命令,你可以使用for循環。

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

爲什麼使用()啓動子shell?這仍然會創建一個包含所有'deps'列表的單個shell命令,儘管至少它不會重複每個項目的命令 –

+0

請參閱Etan Reisner的評論「如果它是一個大的命令行和DEPS中的列表真的是巨大的,可能超過這種方式的單個命令行的長度限制「 – Pierre

+0

如果命令是限制因素而不是」DEPS「本身的內容,這有助於(限制子shell位)。 –

1

正如喬納森Wakely的答案已經提到的,直截了當的答案是

define newline 


endef 

有趣的是,對於除換行符的所有字符還有一個更簡單的方式來獲得非打印字符與一些幫助變量從外殼,例如:

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

但它不會在這裏工作,因爲內置shell函數用空格替換所有換行符。

儘管上述版本仍然有點脆弱,特別是與automake結合時,它會默默地從輸入文件中刪除第二個連續的換行符,將newline變成一個空變量。迫使它保持換行符,我們可以延長段:

blank := 
define newline 

$(blank) 
endef 

最後,每個依存性真正得到一個單獨的shell命令,您需要通過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。我已經在我的版本中修復了它,但我將主要在下面刪除它們。

順便說一下,原來的文章是寫的,我不知道我的解決方案是否相關。但是,我發現自己已經在foreachdefine的中間,並且無法弄清楚如何使用給定的任何其他答案插入換行符。

解決方案:

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)))) 

的標記會不由自主地證明這一點,但BR 2號線是$(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...[$] 

達到相同的(使用^, $來表示該行的開始和結束,其他人可能會知道如何更好地對其進行格式化/註釋。)

我的語法高亮顯然不符合'轉義'括號和尾部空格,但結果是體面的。