Merge "Add boot_images to apex"

This commit is contained in:
Paul Duffin 2021-02-01 10:21:21 +00:00 committed by Gerrit Code Review
commit 4a838dfb3f
4 changed files with 176 additions and 42 deletions

View File

@ -89,6 +89,9 @@ type apexBundleProperties struct {
Multilib apexMultilibProperties
// List of boot images that are embedded inside this APEX bundle.
Boot_images []string
// List of java libraries that are embedded inside this APEX bundle.
Java_libs []string
@ -544,6 +547,7 @@ var (
certificateTag = dependencyTag{name: "certificate"}
executableTag = dependencyTag{name: "executable", payload: true}
fsTag = dependencyTag{name: "filesystem", payload: true}
bootImageTag = dependencyTag{name: "bootImage", payload: true}
javaLibTag = dependencyTag{name: "javaLib", payload: true}
jniLibTag = dependencyTag{name: "jniLib", payload: true}
keyTag = dependencyTag{name: "key"}
@ -721,6 +725,7 @@ func (a *apexBundle) DepsMutator(ctx android.BottomUpMutatorContext) {
// Common-arch dependencies come next
commonVariation := ctx.Config().AndroidCommonTarget.Variations()
ctx.AddFarVariationDependencies(commonVariation, bootImageTag, a.properties.Boot_images...)
ctx.AddFarVariationDependencies(commonVariation, javaLibTag, a.properties.Java_libs...)
ctx.AddFarVariationDependencies(commonVariation, bpfTag, a.properties.Bpfs...)
ctx.AddFarVariationDependencies(commonVariation, fsTag, a.properties.Filesystems...)
@ -730,10 +735,6 @@ func (a *apexBundle) DepsMutator(ctx android.BottomUpMutatorContext) {
if ctx.Config().IsEnvTrue("EMMA_INSTRUMENT_FRAMEWORK") {
ctx.AddFarVariationDependencies(commonVariation, javaLibTag, "jacocoagent")
}
// The ART boot image depends on dex2oat to compile it.
if !java.SkipDexpreoptBootJars(ctx) {
dexpreopt.RegisterToolDeps(ctx)
}
}
// Dependencies for signing
@ -1648,6 +1649,23 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
} else {
ctx.PropertyErrorf("binaries", "%q is neither cc_binary, rust_binary, (embedded) py_binary, (host) blueprint_go_binary, (host) bootstrap_go_binary, nor sh_binary", depName)
}
case bootImageTag:
{
if _, ok := child.(*java.BootImageModule); !ok {
ctx.PropertyErrorf("boot_images", "%q is not a boot_image module", depName)
return false
}
bootImageInfo := ctx.OtherModuleProvider(child, java.BootImageInfoProvider).(java.BootImageInfo)
for arch, files := range bootImageInfo.AndroidBootImageFilesByArchType() {
dirInApex := filepath.Join("javalib", arch.String())
for _, f := range files {
androidMkModuleName := "javalib_" + arch.String() + "_" + filepath.Base(f.String())
// TODO(b/177892522) - consider passing in the boot image module here instead of nil
af := newApexFile(ctx, f, androidMkModuleName, dirInApex, etc, nil)
filesInfo = append(filesInfo, af)
}
}
}
case javaLibTag:
switch child.(type) {
case *java.Library, *java.SdkLibrary, *java.DexImport, *java.SdkLibraryImport, *java.Import:
@ -1862,25 +1880,6 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
return
}
if a.artApex {
// Specific to the ART apex: dexpreopt artifacts for libcore Java libraries. Build rules are
// generated by the dexpreopt singleton, and here we access build artifacts via the global
// boot image config.
for arch, files := range java.DexpreoptedArtApexJars(ctx) {
dirInApex := filepath.Join("javalib", arch.String())
for _, f := range files {
localModule := "javalib_" + arch.String() + "_" + filepath.Base(f.String())
af := newApexFile(ctx, f, localModule, dirInApex, etc, nil)
filesInfo = append(filesInfo, af)
}
}
// Call GetGlobalSoongConfig to initialize it, which may be necessary if dexpreopt is
// disabled for libraries/apps, but boot images are still needed.
if !java.SkipDexpreoptBootJars(ctx) {
dexpreopt.GetGlobalSoongConfig(ctx)
}
}
// Remove duplicates in filesInfo
removeDup := func(filesInfo []apexFile) []apexFile {
encountered := make(map[string]apexFile)

View File

@ -15,6 +15,8 @@
package apex
import (
"reflect"
"strings"
"testing"
"android/soong/android"
@ -83,13 +85,39 @@ func TestBootImages(t *testing.T) {
)
// Make sure that the framework-boot-image is using the correct configuration.
checkBootImage(t, ctx, "framework-boot-image", "platform:foo,platform:bar")
checkBootImage(t, ctx, "framework-boot-image", "platform:foo,platform:bar", `
test_device/dex_bootjars/android/system/framework/arm/boot-foo.art
test_device/dex_bootjars/android/system/framework/arm/boot-foo.oat
test_device/dex_bootjars/android/system/framework/arm/boot-foo.vdex
test_device/dex_bootjars/android/system/framework/arm/boot-bar.art
test_device/dex_bootjars/android/system/framework/arm/boot-bar.oat
test_device/dex_bootjars/android/system/framework/arm/boot-bar.vdex
test_device/dex_bootjars/android/system/framework/arm64/boot-foo.art
test_device/dex_bootjars/android/system/framework/arm64/boot-foo.oat
test_device/dex_bootjars/android/system/framework/arm64/boot-foo.vdex
test_device/dex_bootjars/android/system/framework/arm64/boot-bar.art
test_device/dex_bootjars/android/system/framework/arm64/boot-bar.oat
test_device/dex_bootjars/android/system/framework/arm64/boot-bar.vdex
`)
// Make sure that the art-boot-image is using the correct configuration.
checkBootImage(t, ctx, "art-boot-image", "com.android.art:baz,com.android.art:quuz")
checkBootImage(t, ctx, "art-boot-image", "com.android.art:baz,com.android.art:quuz", `
test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.art
test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.oat
test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.vdex
test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-quuz.art
test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-quuz.oat
test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-quuz.vdex
test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.art
test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.oat
test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.vdex
test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-quuz.art
test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-quuz.oat
test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-quuz.vdex
`)
}
func checkBootImage(t *testing.T, ctx *android.TestContext, moduleName string, expectedConfiguredModules string) {
func checkBootImage(t *testing.T, ctx *android.TestContext, moduleName string, expectedConfiguredModules string, expectedBootImageFiles string) {
t.Helper()
bootImage := ctx.ModuleForTests(moduleName, "android_common").Module().(*java.BootImageModule)
@ -99,6 +127,20 @@ func checkBootImage(t *testing.T, ctx *android.TestContext, moduleName string, e
if actual := modules.String(); actual != expectedConfiguredModules {
t.Errorf("invalid modules for %s: expected %q, actual %q", moduleName, expectedConfiguredModules, actual)
}
// Get a list of all the paths in the boot image sorted by arch type.
allPaths := []string{}
bootImageFilesByArchType := bootImageInfo.AndroidBootImageFilesByArchType()
for _, archType := range android.ArchTypeList() {
if paths, ok := bootImageFilesByArchType[archType]; ok {
for _, path := range paths {
allPaths = append(allPaths, android.NormalizePathForTesting(path))
}
}
}
if expected, actual := strings.TrimSpace(expectedBootImageFiles), strings.TrimSpace(strings.Join(allPaths, "\n")); !reflect.DeepEqual(expected, actual) {
t.Errorf("invalid paths for %s: expected \n%s, actual \n%s", moduleName, expected, actual)
}
}
func modifyDexpreoptConfig(configModifier func(dexpreoptConfig *dexpreopt.GlobalConfig)) func(fs map[string][]byte, config android.Config) {
@ -126,3 +168,61 @@ func withFrameworkBootImageJars(bootJars ...string) func(fs map[string][]byte, c
dexpreoptConfig.BootJars = android.CreateTestConfiguredJarList(bootJars)
})
}
func TestBootImageInApex(t *testing.T) {
ctx, _ := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
boot_images: [
"mybootimage",
],
}
apex_key {
name: "myapex.key",
public_key: "testkey.avbpubkey",
private_key: "testkey.pem",
}
java_library {
name: "foo",
srcs: ["b.java"],
installable: true,
}
java_library {
name: "bar",
srcs: ["b.java"],
installable: true,
}
boot_image {
name: "mybootimage",
image_name: "boot",
apex_available: [
"myapex",
],
}
`,
// Configure some libraries in the framework boot image.
withFrameworkBootImageJars("platform:foo", "platform:bar"),
)
ensureExactContents(t, ctx, "myapex", "android_common_myapex_image", []string{
"javalib/arm/boot-bar.art",
"javalib/arm/boot-bar.oat",
"javalib/arm/boot-bar.vdex",
"javalib/arm/boot-foo.art",
"javalib/arm/boot-foo.oat",
"javalib/arm/boot-foo.vdex",
"javalib/arm64/boot-bar.art",
"javalib/arm64/boot-bar.oat",
"javalib/arm64/boot-bar.vdex",
"javalib/arm64/boot-foo.art",
"javalib/arm64/boot-foo.oat",
"javalib/arm64/boot-foo.vdex",
})
}
// TODO(b/177892522) - add test for host apex.

View File

@ -15,9 +15,11 @@
package java
import (
"fmt"
"strings"
"android/soong/android"
"android/soong/dexpreopt"
"github.com/google/blueprint"
)
@ -38,6 +40,7 @@ type bootImageProperties struct {
type BootImageModule struct {
android.ModuleBase
android.ApexModuleBase
properties bootImageProperties
}
@ -46,6 +49,7 @@ func bootImageFactory() android.Module {
m := &BootImageModule{}
m.AddProperties(&m.properties)
android.InitAndroidArchModule(m, android.HostAndDeviceDefault, android.MultilibCommon)
android.InitApexModule(m)
return m
}
@ -53,6 +57,9 @@ var BootImageInfoProvider = blueprint.NewProvider(BootImageInfo{})
type BootImageInfo struct {
// The image config, internal to this module (and the dex_bootjars singleton).
//
// Will be nil if the BootImageInfo has not been provided for a specific module. That can occur
// when SkipDexpreoptBootJars(ctx) returns true.
imageConfig *bootImageConfig
}
@ -60,12 +67,56 @@ func (i BootImageInfo) Modules() android.ConfiguredJarList {
return i.imageConfig.modules
}
// Get a map from ArchType to the associated boot image's contents for Android.
//
// Extension boot images only return their own files, not the files of the boot images they extend.
func (i BootImageInfo) AndroidBootImageFilesByArchType() map[android.ArchType]android.OutputPaths {
files := map[android.ArchType]android.OutputPaths{}
if i.imageConfig != nil {
for _, variant := range i.imageConfig.variants {
// We also generate boot images for host (for testing), but we don't need those in the apex.
// TODO(b/177892522) - consider changing this to check Os.OsClass = android.Device
if variant.target.Os == android.Android {
files[variant.target.Arch.ArchType] = variant.imagesDeps
}
}
}
return files
}
func (b *BootImageModule) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
tag := ctx.OtherModuleDependencyTag(dep)
if tag == dexpreopt.Dex2oatDepTag {
// The dex2oat tool is only needed for building and is not required in the apex.
return false
}
panic(fmt.Errorf("boot_image module %q should not have a dependency on %q via tag %s", b, dep, android.PrettyPrintTag(tag)))
}
func (b *BootImageModule) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion android.ApiLevel) error {
return nil
}
func (b *BootImageModule) DepsMutator(ctx android.BottomUpMutatorContext) {
if SkipDexpreoptBootJars(ctx) {
return
}
// Add a dependency onto the dex2oat tool which is needed for creating the boot image. The
// path is retrieved from the dependency by GetGlobalSoongConfig(ctx).
dexpreopt.RegisterToolDeps(ctx)
}
func (b *BootImageModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
// Nothing to do if skipping the dexpreopt of boot image jars.
if SkipDexpreoptBootJars(ctx) {
return
}
// Force the GlobalSoongConfig to be created and cached for use by the dex_bootjars
// GenerateSingletonBuildActions method as it cannot create it for itself.
dexpreopt.GetGlobalSoongConfig(ctx)
// Get a map of the image configs that are supported.
imageConfigs := genBootImageConfigs(ctx)

View File

@ -392,22 +392,6 @@ type dexpreoptBootJars struct {
dexpreoptConfigForMake android.WritablePath
}
// Accessor function for the apex package. Returns nil if dexpreopt is disabled.
func DexpreoptedArtApexJars(ctx android.BuilderContext) map[android.ArchType]android.OutputPaths {
if SkipDexpreoptBootJars(ctx) {
return nil
}
// Include dexpreopt files for the primary boot image.
files := map[android.ArchType]android.OutputPaths{}
for _, variant := range artBootImageConfig(ctx).variants {
// We also generate boot images for host (for testing), but we don't need those in the apex.
if variant.target.Os == android.Android {
files[variant.target.Arch.ArchType] = variant.imagesDeps
}
}
return files
}
// Provide paths to boot images for use by modules that depend upon them.
//
// The build rules are created in GenerateSingletonBuildActions().