Implement mixed builds for apex modules.
* Add ApexCqueryInfo to obtain apex artifacts used by the makefile
generator and downstream modules
* Refactor code common to GenerateAndroidBuildActions and ProcessBazelQueryResponse
* Implement android.MixedBuildBuildable for modules
* Enable mixed build for apex modules with payload_type:"image"
Bug: 232085015
Test: treehugger
Change-Id: I9f1e03e5e7a5b5dde35a5db10c253069543ac973
diff --git a/bazel/aquery.go b/bazel/aquery.go
index ae2b107..418b143 100644
--- a/bazel/aquery.go
+++ b/bazel/aquery.go
@@ -574,7 +574,7 @@
// expandTemplateContent substitutes the tokens in a template.
func expandTemplateContent(actionEntry action) string {
- replacerString := []string{}
+ var replacerString []string
for _, pair := range actionEntry.Substitutions {
value := pair.Value
if val, ok := templateActionOverriddenTokens[pair.Key]; ok {
@@ -647,7 +647,7 @@
}
labels = append([]string{currFragment.Label}, labels...)
if currId == currFragment.ParentId {
- return "", fmt.Errorf("Fragment cannot refer to itself as parent %#v", currFragment)
+ return "", fmt.Errorf("fragment cannot refer to itself as parent %#v", currFragment)
}
currId = currFragment.ParentId
}
diff --git a/bazel/cquery/request_type.go b/bazel/cquery/request_type.go
index f5435f2..d32e619 100644
--- a/bazel/cquery/request_type.go
+++ b/bazel/cquery/request_type.go
@@ -1,6 +1,7 @@
package cquery
import (
+ "encoding/json"
"fmt"
"strings"
)
@@ -9,6 +10,7 @@
GetOutputFiles = &getOutputFilesRequestType{}
GetPythonBinary = &getPythonBinaryRequestType{}
GetCcInfo = &getCcInfoType{}
+ GetApexInfo = &getApexInfoType{}
)
type CcInfo struct {
@@ -179,7 +181,7 @@
const expectedLen = 10
splitString := strings.Split(rawString, "|")
if len(splitString) != expectedLen {
- return CcInfo{}, fmt.Errorf("Expected %d items, got %q", expectedLen, splitString)
+ return CcInfo{}, fmt.Errorf("expected %d items, got %q", expectedLen, splitString)
}
outputFilesString := splitString[0]
ccObjectsString := splitString[1]
@@ -215,6 +217,54 @@
}, nil
}
+// Query Bazel for the artifacts generated by the apex modules.
+type getApexInfoType struct{}
+
+// Name returns a string name for this request type. Such request type names must be unique,
+// and must only consist of alphanumeric characters.
+func (g getApexInfoType) Name() string {
+ return "getApexInfo"
+}
+
+// StarlarkFunctionBody returns a starlark function body to process this request type.
+// The returned string is the body of a Starlark function which obtains
+// all request-relevant information about a target and returns a string containing
+// this information. The function should have the following properties:
+// - `target` is the only parameter to this function (a configured target).
+// - The return value must be a string.
+// - The function body should not be indented outside of its own scope.
+func (g getApexInfoType) StarlarkFunctionBody() string {
+ return `info = providers(target)["//build/bazel/rules/apex:apex.bzl%ApexInfo"]
+return "{%s}" % ",".join([
+ json_for_file("signed_output", info.signed_output),
+ json_for_file("unsigned_output", info.unsigned_output),
+ json_for_labels("provides_native_libs", info.provides_native_libs),
+ json_for_labels("requires_native_libs", info.requires_native_libs),
+ json_for_files("bundle_key_pair", info.bundle_key_pair),
+ json_for_files("container_key_pair", info.container_key_pair)
+ ])`
+}
+
+type ApexCqueryInfo struct {
+ SignedOutput string `json:"signed_output"`
+ UnsignedOutput string `json:"unsigned_output"`
+ ProvidesLibs []string `json:"provides_native_libs"`
+ RequiresLibs []string `json:"requires_native_libs"`
+ BundleKeyPair []string `json:"bundle_key_pair"`
+ ContainerKeyPair []string `json:"container_key_pair"`
+}
+
+// ParseResult returns a value obtained by parsing the result of the request's Starlark function.
+// The given rawString must correspond to the string output which was created by evaluating the
+// Starlark given in StarlarkFunctionBody.
+func (g getApexInfoType) ParseResult(rawString string) ApexCqueryInfo {
+ var info ApexCqueryInfo
+ if err := json.Unmarshal([]byte(rawString), &info); err != nil {
+ panic(fmt.Errorf("cannot parse cquery result '%s': %s", rawString, err))
+ }
+ return info
+}
+
// splitOrEmpty is a modification of strings.Split() that returns an empty list
// if the given string is empty.
func splitOrEmpty(s string, sep string) []string {
diff --git a/bazel/cquery/request_type_test.go b/bazel/cquery/request_type_test.go
index 606e285..34248ce 100644
--- a/bazel/cquery/request_type_test.go
+++ b/bazel/cquery/request_type_test.go
@@ -148,13 +148,13 @@
description: "too few result splits",
input: "|",
expectedOutput: CcInfo{},
- expectedErrorMessage: fmt.Sprintf("Expected %d items, got %q", expectedSplits, []string{"", ""}),
+ expectedErrorMessage: fmt.Sprintf("expected %d items, got %q", expectedSplits, []string{"", ""}),
},
{
description: "too many result splits",
input: strings.Repeat("|", expectedSplits+1), // 2 too many
expectedOutput: CcInfo{},
- expectedErrorMessage: fmt.Sprintf("Expected %d items, got %q", expectedSplits, make([]string, expectedSplits+2)),
+ expectedErrorMessage: fmt.Sprintf("expected %d items, got %q", expectedSplits, make([]string, expectedSplits+2)),
},
}
for _, tc := range testCases {
@@ -167,3 +167,40 @@
}
}
}
+
+func TestGetApexInfoParseResults(t *testing.T) {
+ testCases := []struct {
+ description string
+ input string
+ expectedOutput ApexCqueryInfo
+ }{
+ {
+ description: "no result",
+ input: "{}",
+ expectedOutput: ApexCqueryInfo{},
+ },
+ {
+ description: "one result",
+ input: `{"signed_output":"my.apex",` +
+ `"unsigned_output":"my.apex.unsigned",` +
+ `"requires_native_libs":["//bionic/libc:libc","//bionic/libdl:libdl"],` +
+ `"bundle_key_pair":["foo.pem","foo.privkey"],` +
+ `"container_key_pair":["foo.x509.pem", "foo.pk8"],` +
+ `"provides_native_libs":[]}`,
+ expectedOutput: ApexCqueryInfo{
+ SignedOutput: "my.apex",
+ UnsignedOutput: "my.apex.unsigned",
+ RequiresLibs: []string{"//bionic/libc:libc", "//bionic/libdl:libdl"},
+ ProvidesLibs: []string{},
+ BundleKeyPair: []string{"foo.pem", "foo.privkey"},
+ ContainerKeyPair: []string{"foo.x509.pem", "foo.pk8"},
+ },
+ },
+ }
+ for _, tc := range testCases {
+ actualOutput := GetApexInfo.ParseResult(tc.input)
+ if !reflect.DeepEqual(tc.expectedOutput, actualOutput) {
+ t.Errorf("%q: expected %#v != actual %#v", tc.description, tc.expectedOutput, actualOutput)
+ }
+ }
+}