Created
April 16, 2019 05:36
-
-
Save wchargin/5e6a43a203d6c95454aae2886c5b54e4 to your computer and use it in GitHub Desktop.
//tools/list_outputs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From 73d4d74d79d8e058c143d9535ee2680d64a9342f Mon Sep 17 00:00:00 2001 | |
From: William Chargin <wchargin@gmail.com> | |
Date: Mon, 15 Apr 2019 22:14:12 -0700 | |
Subject: [PATCH] Add //tools/list_outputs for aquery result parsing | |
MIME-Version: 1.0 | |
Content-Type: text/plain; charset=UTF-8 | |
Content-Transfer-Encoding: 8bit | |
This commit adds a tool that interprets the results of `bazel aquery` to | |
list all files output by a particular target. | |
See Stack Overflow question: https://stackoverflow.com/q/47859615 | |
Tested: | |
Can be tested informally by running against itself: | |
``` | |
$ tmp="$(mktemp)" | |
$ bazel aquery //tools/list_outputs --output=textproto >"${tmp}" 2>/dev/null | |
$ bazel run //tools/list_outputs -- \ | |
> --aquery_result="${tmp}" \ | |
> --label=//tools/list_outputs:list_outputs \ | |
> 2>/dev/null | |
bazel-out/k8-fastbuild/bin/tools/list_outputs/list_outputs | |
bazel-out/k8-fastbuild/bin/tools/list_outputs/list_outputs.runfiles_manifest | |
bazel-out/k8-fastbuild/bin/tools/list_outputs/list_outputs.runfiles/MANIFEST | |
bazel-out/k8-fastbuild/internal/_middlemen/tools_Slist_Uoutputs_Slist_Uoutputs-runfiles | |
bazel-out/k8-fastbuild/bin/tools/list_outputs/list_outputs.runfiles.SOURCES | |
$ rm "${tmp}" | |
``` | |
The `…/internal/_middlemen/…` file that it lists is correctly parsed | |
from the action graph, but doesn’t actually represent a file on disk. | |
Similar issues can exist with artifacts in external repositories, which | |
look like `external/six_archive/six.py` (again, not a file on disk). | |
It would be nice to add automated tests for this; I just haven’t gotten | |
around to it. | |
Signed-off-by: William Chargin <wchargin@gmail.com> | |
--- | |
tools/list_outputs/BUILD | 32 +++++++++ | |
tools/list_outputs/list_outputs.py | 108 +++++++++++++++++++++++++++++ | |
2 files changed, 140 insertions(+) | |
create mode 100644 tools/list_outputs/BUILD | |
create mode 100644 tools/list_outputs/list_outputs.py | |
diff --git a/tools/list_outputs/BUILD b/tools/list_outputs/BUILD | |
new file mode 100644 | |
index 0000000000..72727d74ce | |
--- /dev/null | |
+++ b/tools/list_outputs/BUILD | |
@@ -0,0 +1,32 @@ | |
+# Copyright 2019 The Bazel Authors. All rights reserved. | |
+# | |
+# Licensed under the Apache License, Version 2.0 (the "License"); | |
+# you may not use this file except in compliance with the License. | |
+# You may obtain a copy of the License at | |
+# | |
+# http://www.apache.org/licenses/LICENSE-2.0 | |
+# | |
+# Unless required by applicable law or agreed to in writing, software | |
+# distributed under the License is distributed on an "AS IS" BASIS, | |
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
+# See the License for the specific language governing permissions and | |
+# limitations under the License. | |
+ | |
+package(default_visibility = ["//visibility:public"]) | |
+ | |
+licenses(["notice"]) # Apache 2.0 | |
+ | |
+filegroup( | |
+ name = "srcs", | |
+ srcs = glob(["**"]), | |
+) | |
+ | |
+py_binary( | |
+ name = "list_outputs", | |
+ srcs = ["list_outputs.py"], | |
+ srcs_version = "PY2AND3", | |
+ deps = [ | |
+ "//third_party/py/abseil", | |
+ "//src/main/protobuf:analysis_py_proto", | |
+ ], | |
+) | |
diff --git a/tools/list_outputs/list_outputs.py b/tools/list_outputs/list_outputs.py | |
new file mode 100644 | |
index 0000000000..cb59846fb8 | |
--- /dev/null | |
+++ b/tools/list_outputs/list_outputs.py | |
@@ -0,0 +1,108 @@ | |
+# Copyright 2019 The Bazel Authors. All rights reserved. | |
+# | |
+# Licensed under the Apache License, Version 2.0 (the "License"); | |
+# you may not use this file except in compliance with the License. | |
+# You may obtain a copy of the License at | |
+# | |
+# http://www.apache.org/licenses/LICENSE-2.0 | |
+# | |
+# Unless required by applicable law or agreed to in writing, software | |
+# distributed under the License is distributed on an "AS IS" BASIS, | |
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
+# See the License for the specific language governing permissions and | |
+# limitations under the License. | |
+r"""Parse an `aquery` result to list outputs created for a target. | |
+ | |
+Use this binary in conjunction with `bazel aquery` to determine the | |
+paths on disk to output files of a target. | |
+ | |
+Example usage: first, query the action graph for the target that you | |
+want to analyze: | |
+ | |
+ bazel aquery //path/to:target --output=textproto >/tmp/aquery_result | |
+ | |
+Then, from the Bazel repository: | |
+ | |
+ bazel run //tools/list_outputs -- \ | |
+ --aquery_result /tmp/aquery_result \ | |
+ --label //path/to:target \ | |
+ ; | |
+ | |
+This will print a list of zero or more output files emitted by the given | |
+target, like: | |
+ | |
+ bazel-out/k8-fastbuild/foo.genfile | |
+ bazel-out/k8-fastbuild/bar.genfile | |
+ | |
+If the provided label does not appear in the output graph, an error will | |
+be raised. | |
+""" | |
+from __future__ import absolute_import | |
+from __future__ import division | |
+from __future__ import print_function | |
+ | |
+import sys | |
+ | |
+from absl import app | |
+from absl import flags | |
+from google.protobuf import text_format | |
+from src.main.protobuf import analysis_pb2 | |
+ | |
+ | |
+flags.DEFINE_string( | |
+ "aquery_result", | |
+ None, | |
+ "Path to file containing result of `bazel aquery ... --output=textproto`.", | |
+) | |
+flags.DEFINE_string( | |
+ "label", | |
+ None, | |
+ "Label whose outputs to print.", | |
+) | |
+ | |
+ | |
+def die(message): | |
+ sys.stderr.write("fatal: %s\n" % (message,)) | |
+ sys.exit(1) | |
+ | |
+ | |
+def main(unused_argv): | |
+ if flags.FLAGS.aquery_result is None: | |
+ raise app.UsageError("Missing `--aquery_result` argument.") | |
+ if flags.FLAGS.label is None: | |
+ raise app.UsageError("Missing `--label` argument.") | |
+ | |
+ if flags.FLAGS.aquery_result == "-": | |
+ aquery_result = sys.stdin.read() | |
+ else: | |
+ with open(flags.FLAGS.aquery_result) as infile: | |
+ aquery_result = infile.read() | |
+ label = flags.FLAGS.label | |
+ | |
+ action_graph_container = analysis_pb2.ActionGraphContainer() | |
+ text_format.Merge(aquery_result, action_graph_container) | |
+ | |
+ matching_targets = [ | |
+ t for t in action_graph_container.targets | |
+ if t.label == label | |
+ ] | |
+ if len(matching_targets) != 1: | |
+ die( | |
+ "expected exactly one target with label %r; found: %s" | |
+ % (label, sorted(t.label for t in matching_targets)) | |
+ ) | |
+ target = matching_targets[0] | |
+ | |
+ all_artifact_ids = frozenset( | |
+ artifact_id | |
+ for action in action_graph_container.actions | |
+ if action.target_id == target.id | |
+ for artifact_id in action.output_ids | |
+ ) | |
+ for artifact in action_graph_container.artifacts: | |
+ if artifact.id in all_artifact_ids: | |
+ print(artifact.exec_path) | |
+ | |
+ | |
+if __name__ == "__main__": | |
+ app.run(main) | |
-- | |
2.21.0.313.ge35b8cb8e2 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment