Implement mixed builds for apex modules, take 2.

* 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"

The first take 6a2b7c40b was setting compressed APEX suffix incorrectly, and
was reverted in 8a3c91494.

Fixes: 239925080 239695521 232085015
Test: treehugger
Change-Id: I1720f8db3c7cc773183d25a815d9b7eeaf7c73ad
This commit is contained in:
Sasha Smundak
2022-07-27 14:51:45 -07:00
parent 28ee99f3c3
commit fe9a5b833d
7 changed files with 338 additions and 106 deletions

View File

@@ -574,7 +574,7 @@ func (a *aqueryArtifactHandler) getOutputPaths(actionEntry action) (outputPaths
// 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 @@ func expandPathFragment(id pathFragmentId, pathFragmentsMap map[pathFragmentId]p
}
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
}

View File

@@ -1,6 +1,7 @@
package cquery
import (
"encoding/json"
"fmt"
"strings"
)
@@ -9,6 +10,7 @@ var (
GetOutputFiles = &getOutputFilesRequestType{}
GetPythonBinary = &getPythonBinaryRequestType{}
GetCcInfo = &getCcInfoType{}
GetApexInfo = &getApexInfoType{}
)
type CcInfo struct {
@@ -179,7 +181,7 @@ func (g getCcInfoType) ParseResult(rawString string) (CcInfo, error) {
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 @@ func (g getCcInfoType) ParseResult(rawString string) (CcInfo, error) {
}, 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 {

View File

@@ -148,13 +148,13 @@ func TestGetCcInfoParseResults(t *testing.T) {
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 TestGetCcInfoParseResults(t *testing.T) {
}
}
}
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)
}
}
}