我正在使用外部工具为工作中的应用程序生成源代码。该工具采用一个充满 JSON 文件的目录树,并生成 C++ 和一些其他实用程序文件。我已经能够设置一个规则和一个目标,当源发生变化时将重新运行生成器,但我正在努力确定如何控制构建顺序。
因为我没有直接的方法来生成将由代码生成器生成的 C++/H 文件列表(因为它是由运行时配置确定的),所以我没有看到任何替代方法,只能运行生成器然后执行输出目录中所有文件的 GLOB。
当我将源 (JSON) 文件设置为我的可执行文件的依赖项时,Boost.Build 会在事情发生变化时运行生成器,但是,它会在运行代码生成器之前计算我的可执行文件的依赖项,因此不会重建正确的事情(例如,如果生成了新文件或更改了头文件,则不会重新编译它们的依赖项),因为该检查是在代码生成器运行之前执行的,因此 GLOB 会获取当前(过期)生成的文件,并且不是新的。
我通过调用 b2 两次来解决这个问题,首先是使用生成代码的目标,然后再次使新生成的代码正确 GLOBbed 并重建我的可执行文件。这可行,但我真的更愿意指定“运行代码生成器,如有必要,然后GLOB 输出目录中的任何文件并确定需要重建的内容”。我没有成功找到合适的搜索词——bbv2 有自己的“生成器”概念,这使得准确找到我正在寻找的内容变得很棘手,而且我还没有找到很好的示例来源。
我的规则看起来像这样,恐怕我不能更具体。这是一个生成器,它接收 *.foo 和 *.bar 类型的文件并创建一堆 CPP 文件和一个 .baz 文件,我用它来确定它是否是最新的。
type.register FOO : foo ;
type.register BAR : bar ;
type.register BAZ : baz ;
generators.register-composing fileset2baz : FOO BAR : BAZ ;
rule fileset2baz ( target : sources * : properties * )
{
# I actually have a switch here based on OS type, but it is not germane to this example
codegen $(target) : $(sources) : $(properties) ;
}
actions codegen
{
./run-the-code-generator
}
# take the fileset and a target object, and invoke the generator
rule fileset ( fileset : target )
{
local FILES = [ path.glob-tree $(fileset) : *.foo *.bar ] ;
local target_baz = $(fileset:B).baz;
baz $(target_baz) : $(FILES) ;
return $(target_baz) ;
}
....然后在我的主要项目中,我有类似的东西:
alias cg : [ fileset $(PATH_TO_FILESET) : $(OUTPUT_DIR) ] ;
lib CodeGen : [ GLOB $(OUTPUT_DIR) : *.cpp *.c ] : : : <include>$(OUTPUT_DIR);
如果我将文件集作为 CodeGen 的源,那么它会评估是否需要重新构建它与是否需要重新构建输出文件。我正在寻找一种方法来强制 cg 运行(如有必要),并且仅在之后,将文件通配到 $(OUTPUT_DIR) 中。