“bazel aquery”对于java_proto_library不返回任何操作信息。

huangapple go评论86阅读模式
英文:

"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 可以得到预期的操作信息,但运行 bazel aquery //:example_java_proto 只返回 INFO 日志:

INFO: 分析目标 //:example_java_proto(已加载0个软件包,配置了15个目标)。
INFO: 找到1个目标...
INFO: 耗时:0.151秒
INFO: 0个进程。
INFO: 构建已成功完成,共计0个操作

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

这是否是 java_proto_library 的特殊问题(我曾看到有关此规则的源代码存档和其他奇怪问题),还是一个错误,或者是我在配置中忽略了什么?

英文:

I'm looking to use bazel aquery to explore inputs and outputs for targets, and have found that java_proto_library produces no output.

For a simple example:

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

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

bazel aquery //:example_proto returns the action information as expected, but bazel aquery //:example_java_proto returns only INFO logging:

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

Full example code at https://github.com/theothertomelliott/bazel-issues/tree/java_proto_aquery

Is this a particular quirk of java_proto_library (I've seen issues raised about src jars and other oddities of this rule), a bug, or something I'm missing in the config?

答案1

得分: 2

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

java_proto_library 实际上并没有注册任何操作:JavaProtoLibrary.java。相反,它在所有的依赖上运行一个切面(aspect):BazelJavaProtoLibraryRule.java#L49-L52。然后,在所有 java_proto_library 的 proto 依赖上评估该切面,将 java proto 操作注册到 proto 依赖上:JavaProtoAspect.java#L206

所以,bazel aquery //:example_java_proto 在于该目标实际上没有任何操作。但是 bazel aquery //:example_proto 也不会返回 java proto 操作。首先需要使用 --include_aspects,这样 aquery 将输出附加到目标的所有切面的信息。

第二个问题是在运行 aquery 时构建图的状态:

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

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

$ <b>bazel aquery //:example_java_proto --include_aspects</b> 2>/dev_null | grep action

(nothing)

$ <b>bazel aquery //:example_proto --include_aspects</b> 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)'
</pre>

所以当首次查询 example_proto 时,返回一个操作,然后查询 example_java_proto,它不返回任何操作,然后再次查询 example_proto,它返回 4 个操作:之前的一个操作和一些 java 操作。这是因为当分析 example_java_proto 时,它注册的切面运行,并且图中现在包含来自切面的操作。

这基本上是设计如此,因为 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 &quot;rdeps(//:example_proto, ...)&quot;
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&gt;/dev_null | grep action
action &#39;Generating Descriptor Set proto_library //:example_proto&#39;
action &#39;Generating Java (Immutable) proto_library //:example_proto&#39;
action &#39;Building libexample_proto-speed.jar (1 source jar)&#39;
action &#39;Compiling Java headers libexample_proto-speed-hjar.jar (1 source jar)&#39;

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

英文:

This is because of the implementation details of java_proto_library, and because of how the build graph is built and how the query functions query it.

java_proto_library doesn't actually register any actions itself: 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

So bazel aquery //:example_java_proto is correct in that that target really has no actions. But bazel aquery //:example_proto also doesn't return java proto actions. The first thing that's needed is --include_aspects, so that aquery outputs information from any aspects attached to the targets.

The 2nd thing is the state of the build graph when aquery is run:

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

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

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

(nothing)

$ <b>bazel aquery //:example_proto --include_aspects</b> 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)'
</pre>

So when example_proto is first queried, it returns 1 action, then example_java_proto is queried, and it returns nothing, then example_proto is queried again, and it returns 4 actions: the one from before, and some java ones. This is because when example_java_proto is analyzed, the aspect it registers runs and the graph now contains the actions from the aspect.

This is basically by design, because Bazel doesn't look at anything beyond what it's asked to query or build. If there were a cc_proto_library in some package somewhere, Bazel won't know about it until it's asked to load or analyze that package. Aspects can come from anywhere, so in order to get complete information, Bazel would have to load every BUILD file in the repository, which won't scale for large repositories.

The rdeps query function can be used to get everything:

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

$ bazel cquery &quot;rdeps(//:example_proto, ...)&quot;
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&gt;/dev/null | grep action
action &#39;Generating Descriptor Set proto_library //:example_proto&#39;
action &#39;Generating Java (Immutable) proto_library //:example_proto&#39;
action &#39;Building libexample_proto-speed.jar (1 source jar)&#39;
action &#39;Compiling Java headers libexample_proto-speed-hjar.jar (1 source jar)&#39;

rdeps(//:example_proto, //...) will find all the reverse dependencies of example_proto, and the //... loads the entire repository. Note that cquery is needed here, rather than query, because query doesn't run the analysis phase, where actions are created, whereas cquery does run the analysis phase.

答案2

得分: 1

java rules 是一个内置的 Bazel 规则,其实现是基于切面(aspects)的,因此如果你首先运行以下命令:

bazel build --nobuild //:example_java_proto  

然后运行:

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

你应该会看到一个带有 Java 特定操作的动作图。

英文:

java rules is a built-in bazel rule, and its implementation is based on aspects,
so if you first run

bazel build --nobuild //:example_java_proto  

and then

bazel aquery &#39;//:example_proto&#39; --include_aspects=true 

you should see an action graph, enriched with java specific actions

huangapple
  • 本文由 发表于 2020年8月16日 04:26:11
  • 转载请务必保留本文链接:https://go.coder-hub.com/63430530.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定