具有动态依赖关系的细粒度构建?

Gre*_*ory 5 coq bazel bazel-rules

我有兴趣了解 bazel 是否可以处理“两阶段构建”,其中根据文件内容发现依赖项,并且必须在依赖它们的代码之前编译依赖项(与 C/C++ 不同,其中依赖项主要是头文件,而不是单独编译)。具体来说,我正在构建类似于 Ocaml 的 Coq 语言。

我创建构建计划的直觉是使用一个(现有的)工具(称为coqdep)来读取文件并返回其所有直接.v依赖项的列表。这是我想到的算法:

  1. coqdep在目标文件和(传递地)其每个依赖文件上调用,
  2. 一旦计算出目标的传递依赖关系,就添加一条规则来构建包含传递依赖关系的.vo目标.v

理想情况下,对coqdep(步骤 1 中)的调用将在构建之间缓存,因此只需要在文件更改时重新计算。并且依赖信息的传递闭包也会被缓存。

是否可以在 bazel 中实现这个?是否有任何关于为此类语言设置构建的指示?天真地,它似乎是一个两阶段构建,我不确定这如何适合 bazel 的编译模型。当我查看 Ocaml 的规则时,它似乎依赖于ocamlbuild满足构建顺序和依赖关系要求,而不是在 bazel 中“本地”执行。

感谢您的任何指示或见解。

Tox*_*ris 2

我正在研究类似的问题,因为我想用 Bazel 构建 ReasonML。

Bazel computes the dependencies between Bazel targets based on the BUILD files in your repository without accessing your source files. The only interaction you can do with the file system during this analysis phase is to list directory contents by using glob in your rule invocations.

Currently, I see four options for getting fine-grained incremental builds with Bazel:

  1. Spell out the fine-grained dependencies in hand-written BUILD files.
  2. Use a tool for generating the BUILD files. You cannot directly wrap that tool in a Bazel rule to have it run during bazel build because the generated BUILD file would be in the output folder, not in the source folder. But you can run rules that call coqdep during the build, and provide an executable that edits the BUILD file in the source folder based on the (cacheable) result of the coqdep calls. Since you can read both the source and the output folder during the build, you could even print a message to the user if they have to run the executable again. Anyway, the full build process would be bazel run //tools/update-coq-build-files && bazel build to reach a fixed point.
  3. Have coarse-grained dependencies in the BUILD files but persistent workers to incrementally rebuild individual targets.
  4. Have coare-grained dependencies in the BUILD files but generate a separate action for each target file and use the unused_inputs_list argument of ctx.actions.run to communicate to Bazel which dependencies where actually unused.

I'm not really sure whether 3 and 4 would actually work or how much effort would be involved, though.