【问题标题】:How to ensure a target is run before all the other build rules in a makefile?如何确保目标在生成文件中的所有其他构建规则之前运行?
【发布时间】:2012-05-23 19:09:46
【问题描述】:

我有一个 C++ 项目,其中包含所有其他 C++ 文件所依赖的生成文件。我试图在任何其他编译开始之前强制生成和编译该文件。通常它就像将该文件放在all: 目标中一样简单,但复杂的是我的 Makefile 也是由构建系统生成的,我只能将片段附加到 Makefile,而不是一般编辑它。

那么,有没有办法通过依赖或其他方式强制生成的文件目标首先运行?我想过使用这样的东西:

cpp_files := $(wildcard src/*.cpp)
$(cpp_files): generated_file.cpp
generated_file.cpp:
    # generate the file here

但它似乎不起作用。作为参考,我的源目录结构是这样的,所以我需要递归收集cpp文件:

src/
|---file1.cpp
|---file2.cpp
|---subdir1/
    |---file3.cpp

gen/
|---generated_file.cpp

【问题讨论】:

    标签: makefile


    【解决方案1】:

    如果你确定这确实是你想要的,这里有一种方法:为一个虚拟文件制定一个规则,makefile 将include

    .PHONY: dummy
    dummy:
        # generate the file here
    
    -include dummy
    

    无论您指定什么目标,Make 都会首先运行dummy 规则,然后自行重启。

    【讨论】:

    • 太棒了!这是一个真正的救生员!
    • 注意:如果你有其他依赖于生成的文件的包含,那么虚拟包含必须跟随这些包含,而不是你想象的在前面。
    • @stunpix 的最后一条评论对我来说真的是一个节省。与 Cygwin 不同,谢谢!
    • 我们可以依靠这种伎俩吗?毕竟,如果GNUmake 完全遵循自己的文档,那么真实文件和PHONY 目标之间的联系就不应该存在。
    • @Vroomfondel:GNUMake 文档并没有做出如此广泛的承诺。
    【解决方案2】:

    实际上,其他cpp 文件不依赖于生成的文件(就 Make 规则而言)。依赖关系图仍然是这样的:

    program
     |
     ^- file1.o
     |   ^- file1.c
     |
     ^- file2.o
     |   ^- file2.c
     |
     ^- generated_file.o
         ^- generated_file.c
             ^- <generator prerequisites>
    

    您的源文件只能依赖于某种生成的头文件(如果这些源是#included)。

    如果您只需要生成一个cpp 文件,那么下面的makefile 就足够了:

    srcs := $(wildcard src/*.cpp src/*/*.cpp)
    
    gen_file := gen/generated_file.cpp
    srcs += $(gen_file)
    
    objs := $(srcs:.cpp=.o)
    
    .PHONY : all
    all : program
    
    program : $(objs)
        @$(LD) ...
    
    %.o : %.c
        @$(CC) ...
    
    $(gen_file) :
        # generate the file here
    

    更新。

    Beta's answer的基础上稍作改进。

    -include generator-task
    .PHONY : generator-task
    
    generator-task : $(gen_files)
    
    $(gen_files) : $(gen_prerequisites)
        # generate the file here
    

    不会在每次调用 Make 时运行生成器,而是仅在其先决条件之一发生变化时重新生成文件。

    【讨论】:

    • 实际上,我确实有一个生成的标题以及cpp 文件。那你提供的代码会不会有很大的不同?
    • @andrei,而不是肯定...在这种情况下,我建议您将代码生成和编译阶段分开。实际上,Beta 的解决方案达到了相同的目标。
    猜你喜欢
    • 1970-01-01
    • 2022-12-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多