为目录目标制作:.DELETE_ON_ERROR

时间:2014-09-09 19:52:27

标签: makefile gnu-make

GNU Make包含一个名为.DELETE_ON_ERROR的特殊目标。如果这包含在Makefile中,Make将删除其构建序列以非零返回状态完成的任何目标。这很有用,因此在后续调用中,Make不会假定目标已正确构建。

这是一个虚拟的例子。

.DELETE_ON_ERROR:

out.dat:    in.dat
            touch out.dat
            false

由于false提供非零返回值,因此构建被视为失败,并且Make会删除out.dat目标。这是广告和预期的行为。但是,当目标是目录时,似乎不会保留此行为。考虑另一个虚拟的例子。

.DELETE_ON_ERROR:

outdir/:    in.dat
            mkdir outdir/
            false

在这种情况下,构建再次失败,但Make不会删除outdir目录。 有什么方法可以指示Make这样做吗?

1 个答案:

答案 0 :(得分:1)

如注释中所述,很难在目录上使用时间戳。几种选择:

  • 代理目标(%.dir)
  • 使用临时文件夹的原子更新。

使用代理目标,可以将Makefile修改为包括一个'%.done'目标,该目标将嵌入清除逻辑。

.PHONY: %.dir

outdir.dir:
    $(MAKE) outdir ; if [ $? -ne 0 ] ; then echo CLEANUP $@ ; rm -rf dir ; false ; fi

outdir: ...  # as before

并使用outdir.dir作为依赖项。不优雅,但是可以完成工作。可能可以转换为规则(免责声明:我没有测试这种方法)。

.PHONY %.dir

%.dir:
    $(MAKE) $* ; if [ $? -ne 0 ] ; then echo CLEANUP $* ; rmd -rf $* ; false ; fi

另一种变化是更改outdir以添加“完成”指示符文件(如果成功完成),并使用代理目标进行验证

%.dir:
    $(MAKE) $* ; if [ ! -f $*.done ] ; then rm -rf $* ; false ; fi

outdir:
   ... commands, any can fail.
   touch $*.done

作为最后的选择(或根据您的情况,选择第一种方法),请考虑为outdir'atomic'构建-创建一个临时文件夹,并在成功后将其重命名为outdir

outdir:
    rm -rf $@.new $@
    mkdir $@.new
    # Command to create outdir.new here
    mv $@.new $@