GNU make:如何在不存在的情况下强制进行中间依赖

时间:2014-02-22 10:01:47

标签: makefile

有三种类型的文件。为方便起见,我们称它们为type1(* .1文件),type2(* .2文件)和type3(* .3文件)。 Type2是通过运行某个命令从type1生成的; type3是通过运行某个其他命令从type2生成的。

Type2文件会老化并变为无效,因此会不时删除。

我有以下规则:

%.2 : %.1
    cmd1 $< -o $@

%.3 : %.2
    cmd2 $< > $@

现在如果xyz.1和xyz.3存在(xyz.1 不比 xyz.3更新),并且xyz.2已被删除,则运行make xyz.3只是说一切都是最新的,没有什么需要做的。

如果我touch xyz.1然后运行make,一切都按预期工作。

需要 make xyz.3首先创建type2文件,然后重新创建type3文件。有没有办法做到这一点?

版本:

  • GNU make 3.81
  • OS X 10.9.1
  • GNU bash 3.2.51

更新1:更清楚地了解了正在使用的模式规则(感谢指出这一点,@路易斯),并且每种类型都存在多个文件。

2 个答案:

答案 0 :(得分:2)

问题

问题是由于使用了模式:

all: foo.3

%.2: %.1
    touch $@

%.3: %.2
    touch $@

在这种情况下,make foo.3; rm foo.2; make foo.3导致重新生成foo.2foo.3。事实上,Makefile以上的make会在创建foo.2之后删除foo.3,因为foo.2是一个中间目标,那就是make与中间目标有关。 (见here。)

解决方案

解决方案很简单,将foo.2列为明确目标:

all: foo.3

foo.2: %.2: %.1
    touch $@

%.3: %.2
    touch $@

通过明确列出foo.2,它不再被视为中间人。上面使用的语法记录为here。据推测,规则适用的文件不止一个,因此更通用的解决方案是:

# Get all files that end in `.1` from the filesystem.
type1_files:=$(wildcard *.1)

# For each file that ends in `.1` we want a corresponding file that ends in `.3`.
type3_files:=$(type1_files:%.1=%.3)

all: $(type3_files)

# For each file that ends in `.1` we want a corresponding file that ends in `.2`.
type2_files:=$(type1_files:%.1=%.2)

# All files that end in `.2` are explicit targets to which this rule applies.
$(type2_files): %.2: %.1
    touch $@

%.3: %.2
    touch $@

答案 1 :(得分:0)

以下按预期工作:

type2 : type1
    @echo building $@ from $<
    touch $@

type3 : type2
    @echo building $@ from $<
    touch $@

结果:

$ touch type1
$ make type3
building type2 from type1
touch type2
building type3 from type2
touch type3
$ rm type2
$ make type3
building type2 from type1
touch type2
building type3 from type2
touch type3

除非你告诉它,否则不应将type2视为中间人,因此你的例子不会出现问题。尝试制作一个测试用例。