Makefile - 仅当文件不存在时才建立依赖关系

Posted

技术标签:

【中文标题】Makefile - 仅当文件不存在时才建立依赖关系【英文标题】:Makefile - Make dependency only if file doesn't exist 【发布时间】:2014-03-11 20:01:09 【问题描述】:

正如标题所说,我只想在某个文件不存在时建立依赖关系,而不是每次更新时。

我有一个根目录(带有 makefile 的那个),其中有一个名为“example”的子目录。在我的根目录中有四个 .h 文件(functions.h、parser.h、node.h 和 exception.h),如果这些 .h 文件不存在,我想将它们复制到“example”子目录在“示例”中。

不幸的是,我不能只创建一个标准依赖项来检查“example”中的头文件,因为每次我将头文件从根目录复制到“example”时,“example”中的头文件都会被认为是更新的,并且会每次运行 make 时都会触发该依赖项。我想要一种方法让我的 makefile 将头文件从根目录复制到“example”,前提是它们不存在于“example”中。

【问题讨论】:

手册非常非常清楚,自动变量(例如$@)在配方中有效。您不能在目标、先决条件或 make 条件语句中使用它们(因为在读入 makefile 时它们会被扩展)。在这些情况下,$@ 扩展为空字符串。 我明白了,但是因为我附加了“example/”,所以 ifeq() 仍然评估为假。感谢您清除它。我已经编辑了我的帖子以专注于剩余的问题。 【参考方案1】:

这就是order-only prerequisites/dependencies 的用途:

但是,有时您会遇到这样的情况,即您希望对要调用的规则施加特定的顺序,而不是在执行这些规则之一时强制更新目标。在这种情况下,您想要定义仅订单的先决条件。可以通过在先决条件列表中放置管道符号 (|) 来指定仅订单先决条件:管道符号左侧的任何先决条件都是正常的;右侧的任何先决条件都是仅订购的。

在你的情况下:

examples/%.h : | %.h
    cp $| $@

另见:Order-only prerequisites do not show up in $^ or $+.

【讨论】:

如果您使用的是 GNU make(而且您可能是),这是一个很好的答案。 @reinierpost 我不确定为什么要使用任何其他品牌。 过去,我一直被其他makes 困住,但事实上,那是很久以前的事了。 谢谢,这个例子有效,但我不确定我是否理解它。我认为 order-only 意味着如果依赖项“%.h”不存在或被更新,它不会触发目标“examples/%.h”。此外,“examples/%.h”是它自己的依赖项,只要将“root”中的文件复制到“examples”,就应该触发它,因为它会更新文件“examples/%.h”。然而,这不是行为意味着它会按照我的意愿去做,但不是我所期望的。您能否详细说明您的解决方案中发生了什么? @Daniel make 不检查仅订单依赖项的时间戳。这意味着它会创建examples/%.h,但不会在其先决条件%.h 更改时对其进行更新。【参考方案2】:

您必须根据相对文件年龄来表达依赖关系。

一种常用的解决方法是使用一个标记操作完成的虚拟(“哨兵”)文件:

examples/%.h.hasbeencopied: %.h
    if [ -f example/$@.h ] || cp -p $< examples/$@.h; \
    then touch $@; \
    else rm -f $@; \
    fi

并使任何规则依赖于example/foo.h 也依赖于example/foo.h.hasbeencopied

【讨论】:

以上是关于Makefile - 仅当文件不存在时才建立依赖关系的主要内容,如果未能解决你的问题,请参考以下文章

仅当目录或文件不存在时才重写规则

仅当文件尚不存在时才将行附加到文件中

php Wordpress - 仅当帖子内容中存在短代码时才加载短代码插件(CF7)依赖项

仅当数组列表尚不存在时才将其添加到数组列表中

Json Schema:仅当深层嵌套对象中存在特定属性时才需要属性

仅当它不存在时才在 SQLite 中创建表