"bazel aquery" returns java_proto_library 没有操作信息

"bazel aquery" returns no action information for java_proto_library

我正在寻找使用 bazel aquery 探索目标的输入和输出,并发现 java_proto_library 没有产生输出。

举个简单的例子:

proto_library(
    name = "example_proto",
    srcs = ["example.proto"],
)

java_proto_library(
    name = "example_java_proto",
    deps = [":example_proto"],
)

bazel aquery //:example_proto returns 预期的操作信息,但 bazel aquery //:example_java_proto returns 只有 INFO 日志记录:

INFO: Analyzed target //:example_java_proto (0 packages loaded, 15 targets configured).
INFO: Found 1 target...
INFO: Elapsed time: 0.151s
INFO: 0 processes.
INFO: Build completed successfully, 0 total actions

完整示例代码位于 https://github.com/theothertomelliott/bazel-issues/tree/java_proto_aquery

这是 java_proto_library 的一个特殊问题(我已经看到有关 src jar 和此规则的其他奇怪之处的问题),一个错误,还是我在配置中遗漏了什么?

这是因为 java_proto_library 的实现细节,以及构建图的构建方式和查询函数查询它的方式。

java_proto_library 本身并没有实际注册任何操作:JavaProtoLibrary.java. Instead, it run an aspect over all its deps: BazelJavaProtoLibraryRule.java#L49-L52. That aspect is then evaluated on all the proto dependencies of the java_proto_library, and registers the java proto actions with the proto dependencies: JavaProtoAspect.java#L206

因此 bazel aquery //:example_java_proto 是正确的,因为该目标确实没有任何操作。但是 bazel aquery //:example_proto 也没有 return java 原型操作。首先需要的是 --include_aspects,以便查询从附加到目标的任何方面输出信息。

第二个是当aquery为运行时构建图的状态:

$ bazel clean
INFO: Starting clean (this may take a while). Consider using --async if the clean takes more than several minutes.

$ bazel aquery //:example_proto --include_aspects 2>/dev/null | grep action
action 'Generating Descriptor Set proto_library //:example_proto'

$ bazel aquery //:example_java_proto --include_aspects 2>/dev/null | grep action

(nothing)

$ bazel aquery //:example_proto --include_aspects 2>/dev/null | grep action
action 'Generating Descriptor Set proto_library //:example_proto'
action 'Generating Java (Immutable) proto_library //:example_proto'
action 'Building libexample_proto-speed.jar (1 source jar)'
action 'Compiling Java headers libexample_proto-speed-hjar.jar (1 source jar)'

所以先查询example_proto时,return是1个action,然后查询example_java_proto,return什么都没有,然后example_proto 再次被查询,它 return 有 4 个动作:之前的那个,还有一些 java 个。这是因为当分析 example_java_proto 时,它注册的方面 运行s 并且图形现在包含来自方面的操作。

这基本上是设计使然,因为 Bazel 不会查看任何超出要求查询或构建的内容。如果某个包中某处有 cc_proto_library,Bazel 在被要求加载或分析该包之前不会知道它。方面可以来自任何地方,因此为了获得完整的信息,Bazel 必须加载存储库中的每个 BUILD 文件,这不会针对大型存储库进行扩展。

可以使用rdeps查询函数获取所有内容:

$ bazel clean
INFO: Starting clean (this may take a while). Consider using --async if the clean takes more than several minutes.

$ bazel cquery "rdeps(//:example_proto, ...)"
INFO: Analyzed 3 targets (20 packages loaded, 908 targets configured).
INFO: Found 3 targets...
//:example_proto (45d0b89373a0dfd75ac4b432cf2b12138c1203b34bdec57557dfef52e7a6ed03)
INFO: Elapsed time: 0.408s
INFO: 0 processes.
INFO: Build completed successfully, 0 total actions

$ bazel aquery //:example_proto --include_aspects 2>/dev/null | grep action
action 'Generating Descriptor Set proto_library //:example_proto'
action 'Generating Java (Immutable) proto_library //:example_proto'
action 'Building libexample_proto-speed.jar (1 source jar)'
action 'Compiling Java headers libexample_proto-speed-hjar.jar (1 source jar)'

rdeps(//:example_proto, //...) 将找到 example_proto 的所有反向依赖项,并且 //... 加载整个存储库。请注意,此处需要 cquery,而不是 query,因为 query 不是 运行 分析阶段,即创建操作的阶段,而 cquery 是 运行分析阶段。

java规则是一个built-in bazel rule, and its implementation is based on aspects, 所以如果你先 运行

bazel build --nobuild //:example_java_proto  

然后

bazel aquery '//:example_proto' --include_aspects=true 

您应该会看到一个动作图,其中包含 java 个具体动作