在Makefile $(foreach)循环中插入换行符

Pie*_*rre 5 newline makefile

我正在编译Makefile中的大量文件。

my.list : ${deps}
    rm -f $@
    $(foreach F,$^,echo "${F}" >> $@;)
Run Code Online (Sandbox Code Playgroud)

但是$ {deps}可能很大,并且对于一个SHELL调用而言,生成的命令行可能太大。是否可以用';'换行符'\ n' 代替?

Jon*_*ely 5

您可以定义一个变量,将其扩展为换行符,如下所示:

define NEWLINE

endef
Run Code Online (Sandbox Code Playgroud)

现在,您可以使用$(NEWLINE)扩展到换行符。

尽管这不会改变任何内容,但foreach仍会生成一个在语句之间带有嵌入式换行符的命令,而不是在语句之​​间具有嵌入​​式换行符的命令;

  • 具有讽刺意味的是,这缺少换行符 ;) (2认同)

Ben*_*nno 5

正如乔纳森·韦克利(Jonathan Wakely)的答案中已经提到的,简单的答案是

define newline


endef
Run Code Online (Sandbox Code Playgroud)

有趣的是,对于除换行符以外的所有字符,有一种更简便的方法可以在shell的帮助下将不可打印的字符转换为变量,例如:

tab := $(shell printf '\011')
Run Code Online (Sandbox Code Playgroud)

但是,这在这里不起作用,因为内置的shell函数用空格替换了所有换行符。

但是,上面的版本仍然有些脆弱,特别是与automake结合使用时,它将自动从输入文件中删除第二个连续的换行符,从而newline变成一个空变量。要强制其保留换行符,我们可以扩展代码段:

blank :=
define newline

$(blank)
endef
Run Code Online (Sandbox Code Playgroud)

最后,要为每个依赖项单独获取一个单独的shell命令,您需要通过eval以下命令运行生成的字符串:

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

endef

$(eval $(call generate-rule,$(deps)))
Run Code Online (Sandbox Code Playgroud)