我正在编译Makefile中的大量文件。
my.list : ${deps}
rm -f $@
$(foreach F,$^,echo "${F}" >> $@;)
Run Code Online (Sandbox Code Playgroud)
但是$ {deps}可能很大,并且对于一个SHELL调用而言,生成的命令行可能太大。是否可以用';'换行符'\ n' 代替?
您可以定义一个变量,将其扩展为换行符,如下所示:
define NEWLINE
endef
Run Code Online (Sandbox Code Playgroud)
现在,您可以使用$(NEWLINE)扩展到换行符。
尽管这不会改变任何内容,但foreach仍会生成一个在语句之间带有嵌入式换行符的命令,而不是在语句之间具有嵌入式换行符的命令;。
正如乔纳森·韦克利(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)