Gnu Make:缺少中间文件时重建

时间:2017-01-23 17:12:42

标签: makefile gnu-make

我正在使用Make来管理数据工作流程(而不是构建软件项目)。我有这样的模式规则:

%.B: %.A
    foo $^ > $@

%.C: %.B
    bar $^ > $@

.SECONDARY:

现在,如果我发现某些.B文件存在问题(例如foo中的错误),我会删除特定的.B文件并执行{{1但是,当然相应的make文件仍然存在并且比它们的.C文件更新,所以没有任何反应。

是否有一种很好的方法可以在缺少依赖项时强制重建.A个文件?基本上我想我正在寻找一种方法来将.C文件提升到完整目标而不是次要或中间。

3 个答案:

答案 0 :(得分:1)

我认为你必须列出实际的.B文件作为all目标(或其他目标,这是在运行期间构建)的先决条件,如果你想确定它们存在于构建完成。我不确定还有其他方法可以做到。

答案 1 :(得分:1)

好像你添加了.SECONDARY目标以避免删除%.B文件而导致问题。因此,您需要使用不同的解决方法而不是.SECONDARY。 如下:

%.B: %.A; cat $^ > $@ && echo B >> $@

%.C: %.B; cat $^ > $@ && echo C >> $@

$(foreach   C,\
            $(sort $(filter %.C,$(MAKECMDGOALS))),\
            $(eval $C: $(patsubst %.C,%.B,$C))\
            $(eval $(patsubst %.C,%.B,$C): $(patsubst %.C,%.A,$C)))

运行上面的makefile:

bash#
$ touch doc.A

bash#
$ make doc.C
cat doc.A > doc.B && echo B >> doc.B
cat doc.B > doc.C && echo C >> doc.C

bash#
$ ls doc.*
doc.A  doc.B  doc.C

bash#
$ rm doc.B

bash#
$ make doc.C
cat doc.A > doc.B && echo B >> doc.B
cat doc.B > doc.C && echo C >> doc.C

bash#
$ ls doc.*
doc.A  doc.B  doc.C

bash#
$ touch doc.A

bash#
$ make doc.C
cat doc.A > doc.B && echo B >> doc.B
cat doc.B > doc.C && echo C >> doc.C

bash#
$ touch doc.B

bash#
$ make doc.C
cat doc.B > doc.C && echo C >> doc.C

变通方法为命令行中指定的所有%.C目标生成显式规则链。不寻常使用GNU Make的不寻常的解决方法!

答案 2 :(得分:1)

我从来没有看到这个问题,即使我做了很多。 也许那是因为我从不使用模式规则。 只需获取目标列表并使用静态模式规则。 也许就像使用$(wildcard)获取源列表一样简单。

# List of sources
As := 1.A 2.A 3.A

${As}: ; touch $@

# List of targets
Bs := ${As:.A=.B}
Cs := ${Bs:.B=.C}

# Static pattern rules
${Bs}: %.B: %.A ; touch $@
${Cs}: %.C: %.B ; touch $@

.PHONY: all
all: ${Cs}

导致

$ make all --warn
touch 1.A
touch 1.B
touch 1.C
touch 2.A
touch 2.B
touch 2.C
touch 3.A
touch 3.B
touch 3.C
$ make all --warn
make: Nothing to be done for 'all'.
$ rm 2.B
$ make all --warn
touch 2.B
touch 2.C

工作很好'联合国