【问题标题】:Include generated makefile without warning message包含生成的 makefile 而没有警告消息
【发布时间】:2014-07-16 03:31:07
【问题描述】:

对于我的一个项目,我会自动生成 makefile 并包含它们,如下所示:

all:
    @echo 'SUCCESS is $(SUCCESS)'

clean:
    rm depend.mk

depend.mk:
    @echo 'Creating $@'
    @echo 'SUCCESS := 1' > $@

.PHONY: all clean

include depend.mk

这可行,但包含行会生成警告消息:

$ make
Makefile:13: depend.mk: No such file or directory
Creating depend.mk
SUCCESS is 1

我想使第一条警告行静音,说depend.mk 不存在。我知道它不存在,因为我编写了一条规则来生成它,所以警告是不必要的(除非当然没有规则)。我不想让忽略包含文件不存在且没有规则的错误,因此在 include 前加上 - 以忽略错误对我不起作用。我想要类似于 bash 的管道 stderr 到 /dev/null 的约定,比如some_cmd 2>/dev/null,但要包含在 make 中。

上面的示例是这种情况的一个非常简化的示例。在我的实际项目中,包含了很多自动生成的 makefile(通过 clang 的自动依赖生成),这意味着新运行的 make 将在我的屏幕上显示这些警告消息。

这样的事情可能吗,还是我只需要处理烦人的警告消息?

【问题讨论】:

  • clang自动依赖文件有具体的规则吗?它们不是作为编译的副作用生成的吗?
  • @EtanReisner 它们是类似于$(BUILDROOT)/%.d: $(CURTOP)/%.c 的模式规则,其中配方是$(CPP) $(CPPFLAGS) -MM -MG -MT $@ -MT $(basename $@).o -MF $@ $<,因此可以在构建任何东西之前生成它们。
  • 你需要在构建任何东西之前生成它们吗?这不是在浪费时间吗?如果需要编译 c 文件,并且 clang 可以同时吐出目标文件和.d 文件,那为什么还要分两遍来做呢?
  • @EtanReisner 现在想想,这确实很有意义。我以前认为它们必须事先生成,否则include 会失败,但我想-include 没有害处,因此只有在之前构建过它们时才会包含它们。毕竟这些规则仅用于确定是否需要重新构建文件。在这种情况下,我是否应该将规则从 %.o: %.c 修改为 %.o %.d: %.c,因为配方会创建两个文件?或者这会导致在解析 Makefile 时生成所有目标文件(因为 include 运行配方)?
  • 阅读this page 了解有关此想法的详细信息(不是我的想法或网站)。特别是“高级自动依赖”部分。

标签: makefile gnu-make


【解决方案1】:

我自己已经多次遇到并(重新重新重新)解决了这个问题。确实,问题在于依赖文件的生成和使用时的思考。

此链接有“分辨率”的详细说明:http://make.mad-scientist.net/papers/advanced-auto-dependency-generation/

基本上归结为依赖文件实际上只需要重建,而不是库/可执行文件的初始构建。结果,您不需要预先生成依赖文件的规则(实际上效率较低),您应该在目标文件步骤期间将它们生成为标记为珍贵的中间文件(因此它们被创建并作为边跟踪- 不应该自动清理的效果文件)。随后的构建将提供可用的文件,这正是您想要实现的整体目标。然后,您可以将其设置为依赖文件的“-include”,并预先知道如果依赖文件生成失败,您的目标文件构建步骤将失败,并立即给出错误,正如您所提到的,这是首选,而不是晦涩难懂和间接的很久以后。

我实际上已经完成了几个相当大的构建系统来实现这种方法,并且效果很好,包括那些使用非 GNU 工具链的系统。对于外部用户来说,它看起来是一样的,但在内部它的执行效率更高,并且没有隐藏潜在的重要错误。

【讨论】:

    【解决方案2】:

    我尝试了很多(很多!)的事情,看看我是否可以阻止或重定向错误消息。没有运气。

    但是当我尝试-include(包括前导破折号)时,它没有给出错误,并且makecleanalldepend.mk 和“默认”都正常工作并且正如预期的那样。

    您是否有不想使用-include 变体的特殊原因?似乎完全符合您的要求,并且不会以任何方式改变 Makefile 的工作方式,只是在第一次通过 Makefile 时不会显示错误。

    【讨论】:

    • 使用-include的问题是,如果某些依赖文件由于某种原因无法生成,则不会显示错误消息。这会导致一些问题,例如难以诊断损坏的构建或不使用make clean 就无法自动更新构建的产品。如果 make 试图包含没有构建规则的文件,我确实希望 make 对我大喊大叫。
    • 但考虑到您的 Makefile 规则,depend.mk 是无条件生成的,因此它应该始终可用。 -include ONLY 抑制不存在文件的错误。文件中的任何垃圾都会按预期导致错误。您应该在创建depend.mk 的命令的尾部添加逻辑以验证depend.mk 是否正确创建。没有其他地方可以测试其存在或内容是合乎逻辑的。 Make 执行命令,如果它们失败,(并且你没有在 cmds 前加上'-'),那么 Make 过程将失败。
    • 请理解我提供的示例 makefile 是我实际使用的更简单的版本(总共接近 1000 行 makefile 代码)。有大量的依赖文件是从不同的地方自动生成的,具有不同的标志、路径和模式。有些是从包含子目录的 makefile 时发生的 $(evaled 函数调用生成的(因为这是一个非递归的 make 构建系统,如“Recursive Make Considered Harmful”论文中所述)。我确实先尝试了-include,但我遇到了难以诊断错误的问题,所以我改变了它。
    • 很公平。但是,如果您的依赖项创建逻辑不健全或至少 fail-fast 不健全,您就会遇到问题,正如您所发现的那样。最坏的情况,这只是一个烦人的输出信息,我内心的强迫症也抱怨它,我正在喂她巧克力让她平静下来。 {叹息}我们试过了。祝你好运。
    • -include depend.nk 是要走的路,以及构建depend.mk 的规则。如果这给出了不一致的结果,那是因为您的 depend.mk 规则被破坏了。请记住,如果出现错误,配方应该创建depend.mk 文件,并且应该退出并出现错误。
    猜你喜欢
    • 2017-08-18
    • 2021-12-14
    • 2016-07-10
    • 2011-02-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-21
    相关资源
    最近更新 更多