diff options
author | Chris Parsons <cparsons@google.com> | 2020-12-10 17:19:18 -0500 |
---|---|---|
committer | Chris Parsons <cparsons@google.com> | 2020-12-15 17:39:23 -0500 |
commit | dbcb1ff46935e4fa848dbe5285a71479492d9ca4 (patch) | |
tree | 1449764e6a4d4fe852b3656f0428a55286c4e01c /bazel | |
parent | fde77e02f3b27b017cdf0005e1f4beacde1ec283 (diff) | |
download | soong-dbcb1ff46935e4fa848dbe5285a71479492d9ca4.tar.gz |
Use aquery to declare bazel actions in the ninja file.
This effectively moves execution of Bazel actions outside of soong_build
and alongside ninja execution of the actual ninja files, whether that be
by ninja or by Bazel itself.
This almost allows for mixed builds and Bazel-as-Ninja-executor to
coexist, but requires hacks explained in b/175307058.
Test: Treehugger
Test: lunch aosp_flame && USE_BAZEL_ANALYSIS=1 m libc
Test: lunch aosp_flame && USE_BAZEL=1 USE_BAZEL_ANALYSIS=1 m libc,
though this requires a hack of the main BUILD file. See b/175307058
Change-Id: Ia2f6b0f1057e8cea3809de66d8287f13d84b510c
Diffstat (limited to 'bazel')
-rw-r--r-- | bazel/Android.bp | 4 | ||||
-rw-r--r-- | bazel/aquery.go | 116 |
2 files changed, 120 insertions, 0 deletions
diff --git a/bazel/Android.bp b/bazel/Android.bp index d557be557..05eddc1b1 100644 --- a/bazel/Android.bp +++ b/bazel/Android.bp @@ -2,10 +2,14 @@ bootstrap_go_package { name: "soong-bazel", pkgPath: "android/soong/bazel", srcs: [ + "aquery.go", "constants.go", "properties.go", ], pluginFor: [ "soong_build", ], + deps: [ + "blueprint", + ], } diff --git a/bazel/aquery.go b/bazel/aquery.go new file mode 100644 index 000000000..69d4fde14 --- /dev/null +++ b/bazel/aquery.go @@ -0,0 +1,116 @@ +// Copyright 2020 Google Inc. 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 bazel + +import ( + "encoding/json" + "strings" + + "github.com/google/blueprint/proptools" +) + +// artifact contains relevant portions of Bazel's aquery proto, Artifact. +// Represents a single artifact, whether it's a source file or a derived output file. +type artifact struct { + Id string + ExecPath string +} + +// KeyValuePair represents Bazel's aquery proto, KeyValuePair. +type KeyValuePair struct { + Key string + Value string +} + +// depSetOfFiles contains relevant portions of Bazel's aquery proto, DepSetOfFiles. +// Represents a data structure containing one or more files. Depsets in Bazel are an efficient +// data structure for storing large numbers of file paths. +type depSetOfFiles struct { + Id string + // TODO(cparsons): Handle non-flat depsets. + DirectArtifactIds []string +} + +// action contains relevant portions of Bazel's aquery proto, Action. +// Represents a single command line invocation in the Bazel build graph. +type action struct { + Arguments []string + EnvironmentVariables []KeyValuePair + InputDepSetIds []string + Mnemonic string + OutputIds []string +} + +// actionGraphContainer contains relevant portions of Bazel's aquery proto, ActionGraphContainer. +// An aquery response from Bazel contains a single ActionGraphContainer proto. +type actionGraphContainer struct { + Artifacts []artifact + Actions []action + DepSetOfFiles []depSetOfFiles +} + +// BuildStatement contains information to register a build statement corresponding (one to one) +// with a Bazel action from Bazel's action graph. +type BuildStatement struct { + Command string + OutputPaths []string + InputPaths []string + Env []KeyValuePair + Mnemonic string +} + +// AqueryBuildStatements returns an array of BuildStatements which should be registered (and output +// to a ninja file) to correspond one-to-one with the given action graph json proto (from a bazel +// aquery invocation). +func AqueryBuildStatements(aqueryJsonProto []byte) []BuildStatement { + buildStatements := []BuildStatement{} + + var aqueryResult actionGraphContainer + json.Unmarshal(aqueryJsonProto, &aqueryResult) + + artifactIdToPath := map[string]string{} + for _, artifact := range aqueryResult.Artifacts { + artifactIdToPath[artifact.Id] = artifact.ExecPath + } + depsetIdToArtifactIds := map[string][]string{} + for _, depset := range aqueryResult.DepSetOfFiles { + depsetIdToArtifactIds[depset.Id] = depset.DirectArtifactIds + } + + for _, actionEntry := range aqueryResult.Actions { + outputPaths := []string{} + for _, outputId := range actionEntry.OutputIds { + // TODO(cparsons): Validate the id is present. + outputPaths = append(outputPaths, artifactIdToPath[outputId]) + } + inputPaths := []string{} + for _, inputDepSetId := range actionEntry.InputDepSetIds { + // TODO(cparsons): Validate the id is present. + for _, inputId := range depsetIdToArtifactIds[inputDepSetId] { + // TODO(cparsons): Validate the id is present. + inputPaths = append(inputPaths, artifactIdToPath[inputId]) + } + } + buildStatement := BuildStatement{ + Command: strings.Join(proptools.ShellEscapeList(actionEntry.Arguments), " "), + OutputPaths: outputPaths, + InputPaths: inputPaths, + Env: actionEntry.EnvironmentVariables, + Mnemonic: actionEntry.Mnemonic} + buildStatements = append(buildStatements, buildStatement) + } + + return buildStatements +} |