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

时间:2015-04-15 13:19:17

标签: makefile newline

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

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

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

5 个答案:

答案 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...[$]

实现相同的目标(使用^,$来表示该行的开头和结尾。其他人可能会知道如何更好地格式化/注释它。)

我的语法荧光笔显然对'转义'括号和尾随空格不感兴趣,但结果还不错。