我正在编译Makefile中的大量文件。
my.list : ${deps}
rm -f $@
$(foreach F,$^,echo "${F}" >> $@;)
但是$ {deps}可能很大,并且生成的命令行对于一个SHELL调用来说可能太大。是否可以用换行符'\ n'替换';'
?
答案 0 :(得分:5)
正如Jonathan Wakely的回答中所提到的,直截了当的回答是
define newline
endef
有趣的是,对于除换行之外的所有字符,有一种更简单的方法可以在shell的帮助下将不可打印的字符转换为变量,例如:
tab := $(shell printf '\011')
但是,它不会在这里工作,因为内置shell函数用空格替换所有换行符。
上面的版本仍然有点脆弱,特别是当与automake结合使用时,它会默默地从输入文件中删除第二个连续的换行符,将newline
转换为空变量。为了强制它保留换行符,我们可以扩展代码段:
blank :=
define newline
$(blank)
endef
最后,要为每个依赖项实际获取单独的shell命令,您需要通过eval
运行生成的字符串:
define generate-rule =
my.list : $(1)
rm -f $$@
$(foreach F,$$^,$(newline)$(tab)echo "${F}" >> $@)
endef
$(eval $(call generate-rule,$(deps)))
答案 1 :(得分:1)
您可以定义一个扩展为换行符的变量,如下所示:
define NEWLINE
endef
现在,您可以使用$(NEWLINE)
扩展到换行符。
这不会改变任何东西,foreach
仍会生成一个命令,在语句之间嵌入换行符,而不是在语句之间使用;
的单个命令。
答案 2 :(得分:1)
最直接的答案可能是使用:
@printf "\n"
您也可以像我通常那样使用它,以在执行每个新的make目标时显示说明。目标示例:
.PHONY: clean-version
clean-version: ## Reset version back to committed version number
@printf "\n## Reset version to last committed version number ##\n\n"; \
$(GIT) checkout $(VERSION_FILE);
答案 3 :(得分:0)
更换';'通过回车将产生相同大小的字符串,受到同样的问题。
"的foreach"只是一个字符串扩展。如果要为每个项目执行单独的命令,可以使用for循环。
my.list : ${deps}
rm -f $@
(for F in $^; do echo $$F >> $@ ; done)
答案 4 :(得分: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 $$@
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 $$@
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...[$]
实现相同的目标(使用^,$来表示该行的开头和结尾。其他人可能会知道如何更好地格式化/注释它。)
我的语法荧光笔显然对'转义'括号和尾随空格不感兴趣,但结果还不错。