Merge "Allow using updatable boot jars in dexpreopt (but don't use them yet)." am: 2258cbbe42
Original change: https://android-review.googlesource.com/c/platform/build/soong/+/1647188 Change-Id: I7097c866c3dd01fa8e19c8aa74c4b74c1e78538b
This commit is contained in:
committed by
Automerger Merge Worker
commit
29dae7ed73
@@ -33,6 +33,8 @@ type GlobalConfig struct {
|
|||||||
|
|
||||||
OnlyPreoptBootImageAndSystemServer bool // only preopt jars in the boot image or system server
|
OnlyPreoptBootImageAndSystemServer bool // only preopt jars in the boot image or system server
|
||||||
|
|
||||||
|
PreoptWithUpdatableBcp bool // If updatable boot jars are included in dexpreopt or not.
|
||||||
|
|
||||||
UseArtImage bool // use the art image (use other boot class path dex files without image)
|
UseArtImage bool // use the art image (use other boot class path dex files without image)
|
||||||
|
|
||||||
HasSystemOther bool // store odex files that match PatternsOnSystemOther on the system_other partition
|
HasSystemOther bool // store odex files that match PatternsOnSystemOther on the system_other partition
|
||||||
|
@@ -117,3 +117,17 @@ func FixtureSetBootJars(bootJars ...string) android.FixturePreparer {
|
|||||||
dexpreoptConfig.BootJars = android.CreateTestConfiguredJarList(bootJars)
|
dexpreoptConfig.BootJars = android.CreateTestConfiguredJarList(bootJars)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FixtureSetUpdatableBootJars sets the UpdatableBootJars property in the global config.
|
||||||
|
func FixtureSetUpdatableBootJars(bootJars ...string) android.FixturePreparer {
|
||||||
|
return FixtureModifyGlobalConfig(func(dexpreoptConfig *GlobalConfig) {
|
||||||
|
dexpreoptConfig.UpdatableBootJars = android.CreateTestConfiguredJarList(bootJars)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// FixtureSetPreoptWithUpdatableBcp sets the PreoptWithUpdatableBcp property in the global config.
|
||||||
|
func FixtureSetPreoptWithUpdatableBcp(value bool) android.FixturePreparer {
|
||||||
|
return FixtureModifyGlobalConfig(func(dexpreoptConfig *GlobalConfig) {
|
||||||
|
dexpreoptConfig.PreoptWithUpdatableBcp = value
|
||||||
|
})
|
||||||
|
}
|
||||||
|
@@ -26,6 +26,7 @@ import (
|
|||||||
|
|
||||||
"android/soong/android"
|
"android/soong/android"
|
||||||
"android/soong/cc"
|
"android/soong/cc"
|
||||||
|
"android/soong/dexpreopt"
|
||||||
"android/soong/genrule"
|
"android/soong/genrule"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -2422,6 +2423,66 @@ func TestUsesLibraries(t *testing.T) {
|
|||||||
`#PCL[/system/framework/android.test.mock.jar] `)
|
`#PCL[/system/framework/android.test.mock.jar] `)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDexpreoptBcp(t *testing.T) {
|
||||||
|
bp := `
|
||||||
|
java_sdk_library {
|
||||||
|
name: "foo",
|
||||||
|
srcs: ["a.java"],
|
||||||
|
api_packages: ["foo"],
|
||||||
|
sdk_version: "current",
|
||||||
|
}
|
||||||
|
|
||||||
|
java_sdk_library {
|
||||||
|
name: "bar",
|
||||||
|
srcs: ["a.java"],
|
||||||
|
api_packages: ["bar"],
|
||||||
|
permitted_packages: ["bar"],
|
||||||
|
sdk_version: "current",
|
||||||
|
}
|
||||||
|
|
||||||
|
android_app {
|
||||||
|
name: "app",
|
||||||
|
srcs: ["a.java"],
|
||||||
|
sdk_version: "current",
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
with bool
|
||||||
|
expect string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "with updatable bcp",
|
||||||
|
with: true,
|
||||||
|
expect: "/system/framework/foo.jar:/system/framework/bar.jar",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "without updatable bcp",
|
||||||
|
with: false,
|
||||||
|
expect: "/system/framework/foo.jar",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range testCases {
|
||||||
|
t.Run(test.name, func(t *testing.T) {
|
||||||
|
result := android.GroupFixturePreparers(
|
||||||
|
prepareForJavaTest,
|
||||||
|
PrepareForTestWithJavaSdkLibraryFiles,
|
||||||
|
FixtureWithLastReleaseApis("runtime-library", "foo", "bar"),
|
||||||
|
dexpreopt.FixtureSetBootJars("platform:foo"),
|
||||||
|
dexpreopt.FixtureSetUpdatableBootJars("platform:bar"),
|
||||||
|
dexpreopt.FixtureSetPreoptWithUpdatableBcp(test.with),
|
||||||
|
).RunTestWithBp(t, bp)
|
||||||
|
|
||||||
|
app := result.ModuleForTests("app", "android_common")
|
||||||
|
cmd := app.Rule("dexpreopt").RuleParams.Command
|
||||||
|
bcp := " -Xbootclasspath-locations:" + test.expect + " " // space at the end matters
|
||||||
|
android.AssertStringDoesContain(t, "dexpreopt app bcp", cmd, bcp)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestCodelessApp(t *testing.T) {
|
func TestCodelessApp(t *testing.T) {
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
name string
|
name string
|
||||||
|
@@ -160,14 +160,17 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Wr
|
|||||||
|
|
||||||
globalSoong := dexpreopt.GetGlobalSoongConfig(ctx)
|
globalSoong := dexpreopt.GetGlobalSoongConfig(ctx)
|
||||||
global := dexpreopt.GetGlobalConfig(ctx)
|
global := dexpreopt.GetGlobalConfig(ctx)
|
||||||
|
|
||||||
|
isSystemServerJar := inList(ctx.ModuleName(), global.SystemServerJars)
|
||||||
|
|
||||||
bootImage := defaultBootImageConfig(ctx)
|
bootImage := defaultBootImageConfig(ctx)
|
||||||
dexFiles := bootImage.dexPathsDeps.Paths()
|
|
||||||
// The dex locations for all Android variants are identical.
|
|
||||||
dexLocations := bootImage.getAnyAndroidVariant().dexLocationsDeps
|
|
||||||
if global.UseArtImage {
|
if global.UseArtImage {
|
||||||
bootImage = artBootImageConfig(ctx)
|
bootImage = artBootImageConfig(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// System server jars are an exception: they are dexpreopted without updatable bootclasspath.
|
||||||
|
dexFiles, dexLocations := bcpForDexpreopt(ctx, global.PreoptWithUpdatableBcp && !isSystemServerJar)
|
||||||
|
|
||||||
targets := ctx.MultiTargets()
|
targets := ctx.MultiTargets()
|
||||||
if len(targets) == 0 {
|
if len(targets) == 0 {
|
||||||
// assume this is a java library, dexpreopt for all arches for now
|
// assume this is a java library, dexpreopt for all arches for now
|
||||||
@@ -176,7 +179,7 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Wr
|
|||||||
targets = append(targets, target)
|
targets = append(targets, target)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if inList(ctx.ModuleName(), global.SystemServerJars) && !d.isSDKLibrary {
|
if isSystemServerJar && !d.isSDKLibrary {
|
||||||
// If the module is not an SDK library and it's a system server jar, only preopt the primary arch.
|
// If the module is not an SDK library and it's a system server jar, only preopt the primary arch.
|
||||||
targets = targets[:1]
|
targets = targets[:1]
|
||||||
}
|
}
|
||||||
@@ -237,7 +240,7 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Wr
|
|||||||
DexPreoptImagesDeps: imagesDeps,
|
DexPreoptImagesDeps: imagesDeps,
|
||||||
DexPreoptImageLocations: imageLocations,
|
DexPreoptImageLocations: imageLocations,
|
||||||
|
|
||||||
PreoptBootClassPathDexFiles: dexFiles,
|
PreoptBootClassPathDexFiles: dexFiles.Paths(),
|
||||||
PreoptBootClassPathDexLocations: dexLocations,
|
PreoptBootClassPathDexLocations: dexLocations,
|
||||||
|
|
||||||
PreoptExtractedApk: false,
|
PreoptExtractedApk: false,
|
||||||
|
@@ -439,6 +439,8 @@ func (d *dexpreoptBootJars) GenerateSingletonBuildActions(ctx android.SingletonC
|
|||||||
// Create boot image for the ART apex (build artifacts are accessed via the global boot image config).
|
// Create boot image for the ART apex (build artifacts are accessed via the global boot image config).
|
||||||
d.otherImages = append(d.otherImages, buildBootImage(ctx, artBootImageConfig(ctx)))
|
d.otherImages = append(d.otherImages, buildBootImage(ctx, artBootImageConfig(ctx)))
|
||||||
|
|
||||||
|
copyUpdatableBootJars(ctx)
|
||||||
|
|
||||||
dumpOatRules(ctx, d.defaultBootImage)
|
dumpOatRules(ctx, d.defaultBootImage)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -630,6 +632,21 @@ func buildBootImage(ctx android.SingletonContext, image *bootImageConfig) *bootI
|
|||||||
return image
|
return image
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Generate commands that will copy updatable boot jars to predefined paths in the global config.
|
||||||
|
func copyUpdatableBootJars(ctx android.SingletonContext) {
|
||||||
|
config := GetUpdatableBootConfig(ctx)
|
||||||
|
getBootJarFunc := func(module android.Module) (int, android.Path) {
|
||||||
|
index, jar, _ := getBootJar(ctx, config.modules, module, "configured in updatable boot jars ")
|
||||||
|
return index, jar
|
||||||
|
}
|
||||||
|
missingDeps := findAndCopyBootJars(ctx, config.modules, config.dexPaths, getBootJarFunc)
|
||||||
|
// Ignoring missing dependencies here. Ideally they should be added to the dexpreopt rule, but
|
||||||
|
// that is not possible as this rule is created after dexpreopt rules (it's in a singleton
|
||||||
|
// context, and they are in a module context). The true fix is to add dependencies from the
|
||||||
|
// dexpreopted modules on updatable boot jars and avoid this copying altogether.
|
||||||
|
_ = missingDeps
|
||||||
|
}
|
||||||
|
|
||||||
// Generate boot image build rules for a specific target.
|
// Generate boot image build rules for a specific target.
|
||||||
func buildBootImageVariant(ctx android.SingletonContext, image *bootImageVariant,
|
func buildBootImageVariant(ctx android.SingletonContext, image *bootImageVariant,
|
||||||
profile android.Path, missingDeps []string) android.WritablePaths {
|
profile android.Path, missingDeps []string) android.WritablePaths {
|
||||||
@@ -997,8 +1014,11 @@ func (d *dexpreoptBootJars) MakeVars(ctx android.MakeVarsContext) {
|
|||||||
image := d.defaultBootImage
|
image := d.defaultBootImage
|
||||||
if image != nil {
|
if image != nil {
|
||||||
ctx.Strict("DEXPREOPT_IMAGE_PROFILE_BUILT_INSTALLED", image.profileInstalls.String())
|
ctx.Strict("DEXPREOPT_IMAGE_PROFILE_BUILT_INSTALLED", image.profileInstalls.String())
|
||||||
ctx.Strict("DEXPREOPT_BOOTCLASSPATH_DEX_FILES", strings.Join(image.dexPathsDeps.Strings(), " "))
|
|
||||||
ctx.Strict("DEXPREOPT_BOOTCLASSPATH_DEX_LOCATIONS", strings.Join(image.getAnyAndroidVariant().dexLocationsDeps, " "))
|
global := dexpreopt.GetGlobalConfig(ctx)
|
||||||
|
dexPaths, dexLocations := bcpForDexpreopt(ctx, global.PreoptWithUpdatableBcp)
|
||||||
|
ctx.Strict("DEXPREOPT_BOOTCLASSPATH_DEX_FILES", strings.Join(dexPaths.Strings(), " "))
|
||||||
|
ctx.Strict("DEXPREOPT_BOOTCLASSPATH_DEX_LOCATIONS", strings.Join(dexLocations, " "))
|
||||||
|
|
||||||
var imageNames []string
|
var imageNames []string
|
||||||
// TODO: the primary ART boot image should not be exposed to Make, as it is installed in a
|
// TODO: the primary ART boot image should not be exposed to Make, as it is installed in a
|
||||||
|
@@ -176,6 +176,57 @@ func defaultBootclasspath(ctx android.PathContext) []string {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Updatable boot config allows to access build/install paths of updatable boot jars without going
|
||||||
|
// through the usual trouble of registering dependencies on those modules and extracting build paths
|
||||||
|
// from those dependencies.
|
||||||
|
type updatableBootConfig struct {
|
||||||
|
// A list of updatable boot jars.
|
||||||
|
modules android.ConfiguredJarList
|
||||||
|
|
||||||
|
// A list of predefined build paths to updatable boot jars. They are configured very early,
|
||||||
|
// before the modules for these jars are processed and the actual paths are generated, and
|
||||||
|
// later on a singleton adds commands to copy actual jars to the predefined paths.
|
||||||
|
dexPaths android.WritablePaths
|
||||||
|
|
||||||
|
// A list of dex locations (a.k.a. on-device paths) to the boot jars.
|
||||||
|
dexLocations []string
|
||||||
|
}
|
||||||
|
|
||||||
|
var updatableBootConfigKey = android.NewOnceKey("updatableBootConfig")
|
||||||
|
|
||||||
|
// Returns updatable boot config.
|
||||||
|
func GetUpdatableBootConfig(ctx android.PathContext) updatableBootConfig {
|
||||||
|
return ctx.Config().Once(updatableBootConfigKey, func() interface{} {
|
||||||
|
updatableBootJars := dexpreopt.GetGlobalConfig(ctx).UpdatableBootJars
|
||||||
|
|
||||||
|
dir := android.PathForOutput(ctx, ctx.Config().DeviceName(), "updatable_bootjars")
|
||||||
|
dexPaths := updatableBootJars.BuildPaths(ctx, dir)
|
||||||
|
|
||||||
|
dexLocations := updatableBootJars.DevicePaths(ctx.Config(), android.Android)
|
||||||
|
|
||||||
|
return updatableBootConfig{updatableBootJars, dexPaths, dexLocations}
|
||||||
|
}).(updatableBootConfig)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns a list of paths and a list of locations for the boot jars used in dexpreopt (to be
|
||||||
|
// passed in -Xbootclasspath and -Xbootclasspath-locations arguments for dex2oat).
|
||||||
|
func bcpForDexpreopt(ctx android.PathContext, withUpdatable bool) (android.WritablePaths, []string) {
|
||||||
|
// Non-updatable boot jars (they are used both in the boot image and in dexpreopt).
|
||||||
|
bootImage := defaultBootImageConfig(ctx)
|
||||||
|
dexPaths := bootImage.dexPathsDeps
|
||||||
|
// The dex locations for all Android variants are identical.
|
||||||
|
dexLocations := bootImage.getAnyAndroidVariant().dexLocationsDeps
|
||||||
|
|
||||||
|
if withUpdatable {
|
||||||
|
// Updatable boot jars (they are used only in dexpreopt, but not in the boot image).
|
||||||
|
updBootConfig := GetUpdatableBootConfig(ctx)
|
||||||
|
dexPaths = append(dexPaths, updBootConfig.dexPaths...)
|
||||||
|
dexLocations = append(dexLocations, updBootConfig.dexLocations...)
|
||||||
|
}
|
||||||
|
|
||||||
|
return dexPaths, dexLocations
|
||||||
|
}
|
||||||
|
|
||||||
var defaultBootclasspathKey = android.NewOnceKey("defaultBootclasspath")
|
var defaultBootclasspathKey = android.NewOnceKey("defaultBootclasspath")
|
||||||
|
|
||||||
var copyOf = android.CopyOf
|
var copyOf = android.CopyOf
|
||||||
|
Reference in New Issue
Block a user