From 40f9f3c061e30af857a54f35a5dd670d75e1c87d Mon Sep 17 00:00:00 2001 From: Martin Stjernholm Date: Mon, 20 Jan 2020 18:12:23 +0000 Subject: Reland: Move the Once cache for dexpreopt.GlobalConfig into the dexpreopt package. Preparation for a future CL that will need to get the make-written GlobalConfig from within dexpreopt. Also rename the Load*Config functions to Parse*Config, since they don't actually load the config files anymore. This relands https://r.android.com/1211982. Bug: 145934348 Test: m Change-Id: Icb9332a93811d77d2d8b06e983b92501b180a358 --- java/java.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'java/java.go') diff --git a/java/java.go b/java/java.go index d84d16272..b20f5f244 100644 --- a/java/java.go +++ b/java/java.go @@ -105,7 +105,7 @@ func DexpreoptedSystemServerJars(config android.Config) *[]string { // order (which is partial and non-deterministic). This pass adds additional dependencies between // jars, making the order total and deterministic. It also constructs a global ordered list. func systemServerJarsDepsMutator(ctx android.BottomUpMutatorContext) { - jars := dexpreopt.NonUpdatableSystemServerJars(ctx, dexpreoptGlobalConfig(ctx)) + jars := dexpreopt.NonUpdatableSystemServerJars(ctx, dexpreopt.GetGlobalConfig(ctx)) name := ctx.ModuleName() if android.InList(name, jars) { dexpreoptedSystemServerJarsLock.Lock() -- cgit v1.2.3-59-g8ed1b From d90676fdde67b6e3f76819092c86882aa9306a7c Mon Sep 17 00:00:00 2001 From: Martin Stjernholm Date: Sat, 11 Jan 2020 00:37:30 +0000 Subject: Reland: Get the dex2oat host tool path from module dependency on the binary module. This uses the Once cache for GlobalSoongConfig to propagate the dex2oat path from a module dependency to the singletons (both the one that writes out dexpreopt_soong.config and the one that creates the dexpreopted boot images). Unless dexpreopting is disabled altogether through DisablePreopt in dexpreopt.config, that means: - We must ensure at least one module registers a dex2oat tool dependency and resolves a GlobalSoongConfig using it, or else the singletons fail. That means we litter dex2oat dependencies in java modules even when they won't get dexpreopted and hence don't really need them. - We still assume there's at least one java_library or android_app in the build. This relands https://r.android.com/1205730 without changes - the necessary fixes are in the child CLs. Bug: 145934348 Test: m (check that out/soong/dexpreopt_soong.config points to dex2oatd64) Test: env USE_DEX2OAT_DEBUG=false m (check that out/soong/dexpreopt_soong.config points to dex2oat64) Test: env OUT_DIR=out-tools prebuilts/build-tools/build-prebuilts.sh on the aosp-build-tools branch Change-Id: I66661711b317d1e4ec434861982919bdde19b575 --- dexpreopt/Android.bp | 1 + dexpreopt/config.go | 105 ++++++++++++++++++++++++++++++++++++++++++++++----- dexpreopt/testing.go | 47 +++++++++++++++++++++++ java/app.go | 2 + java/java.go | 15 ++++++++ java/java_test.go | 4 ++ 6 files changed, 164 insertions(+), 10 deletions(-) create mode 100644 dexpreopt/testing.go (limited to 'java/java.go') diff --git a/dexpreopt/Android.bp b/dexpreopt/Android.bp index c5f24e273..b8f7ea682 100644 --- a/dexpreopt/Android.bp +++ b/dexpreopt/Android.bp @@ -4,6 +4,7 @@ bootstrap_go_package { srcs: [ "config.go", "dexpreopt.go", + "testing.go", ], testSrcs: [ "dexpreopt_test.go", diff --git a/dexpreopt/config.go b/dexpreopt/config.go index 7a404f5a6..94f128383 100644 --- a/dexpreopt/config.go +++ b/dexpreopt/config.go @@ -16,8 +16,11 @@ package dexpreopt import ( "encoding/json" + "fmt" "strings" + "github.com/google/blueprint" + "android/soong/android" ) @@ -297,6 +300,71 @@ func ParseModuleConfig(ctx android.PathContext, data []byte) (ModuleConfig, erro return config.ModuleConfig, nil } +// dex2oatModuleName returns the name of the module to use for the dex2oat host +// tool. It should be a binary module with public visibility that is compiled +// and installed for host. +func dex2oatModuleName(config android.Config) string { + // Default to the debug variant of dex2oat to help find bugs. + // Set USE_DEX2OAT_DEBUG to false for only building non-debug versions. + if config.Getenv("USE_DEX2OAT_DEBUG") == "false" { + return "dex2oat" + } else { + return "dex2oatd" + } +} + +var dex2oatDepTag = struct { + blueprint.BaseDependencyTag +}{} + +type DexPreoptModule interface { + dexPreoptModuleSignature() // Not called - only for type detection. +} + +// RegisterToolDepsMutator registers a mutator that adds the necessary +// dependencies to binary modules for tools that are required later when +// Get(Cached)GlobalSoongConfig is called. It should be passed to +// android.RegistrationContext.FinalDepsMutators, and module types that need +// dependencies also need to embed DexPreoptModule. +func RegisterToolDepsMutator(ctx android.RegisterMutatorsContext) { + ctx.BottomUp("dexpreopt_tool_deps", toolDepsMutator).Parallel() +} + +func toolDepsMutator(ctx android.BottomUpMutatorContext) { + if GetGlobalConfig(ctx).DisablePreopt { + // Only register dependencies if dexpreopting is enabled. Necessary to avoid + // them in non-platform builds where dex2oat etc isn't available. + // + // It would be nice to not register this mutator at all then, but + // RegisterMutatorsContext available at registration doesn't have the state + // necessary to pass as PathContext to constructPath etc. + return + } + if _, ok := ctx.Module().(DexPreoptModule); !ok { + return + } + dex2oatBin := dex2oatModuleName(ctx.Config()) + v := ctx.Config().BuildOSTarget.Variations() + ctx.AddFarVariationDependencies(v, dex2oatDepTag, dex2oatBin) +} + +func dex2oatPathFromDep(ctx android.ModuleContext) android.Path { + dex2oatBin := dex2oatModuleName(ctx.Config()) + + dex2oatModule := ctx.GetDirectDepWithTag(dex2oatBin, dex2oatDepTag) + if dex2oatModule == nil { + // If this happens there's probably a missing call to AddToolDeps in DepsMutator. + panic(fmt.Sprintf("Failed to lookup %s dependency", dex2oatBin)) + } + + dex2oatPath := dex2oatModule.(android.HostToolProvider).HostToolPath() + if !dex2oatPath.Valid() { + panic(fmt.Sprintf("Failed to find host tool path in %s", dex2oatModule)) + } + + return dex2oatPath.Path() +} + // createGlobalSoongConfig creates a GlobalSoongConfig from the current context. // Should not be used in dexpreopt_gen. func createGlobalSoongConfig(ctx android.ModuleContext) GlobalSoongConfig { @@ -307,18 +375,9 @@ func createGlobalSoongConfig(ctx android.ModuleContext) GlobalSoongConfig { panic("This should not be called from tests. Please call GlobalSoongConfigForTests somewhere in the test setup.") } - // Default to debug version to help find bugs. - // Set USE_DEX2OAT_DEBUG to false for only building non-debug versions. - var dex2oatBinary string - if ctx.Config().Getenv("USE_DEX2OAT_DEBUG") == "false" { - dex2oatBinary = "dex2oat" - } else { - dex2oatBinary = "dex2oatd" - } - return GlobalSoongConfig{ Profman: ctx.Config().HostToolPath(ctx, "profman"), - Dex2oat: ctx.Config().HostToolPath(ctx, dex2oatBinary), + Dex2oat: dex2oatPathFromDep(ctx), Aapt: ctx.Config().HostToolPath(ctx, "aapt"), SoongZip: ctx.Config().HostToolPath(ctx, "soong_zip"), Zip2zip: ctx.Config().HostToolPath(ctx, "zip2zip"), @@ -327,6 +386,16 @@ func createGlobalSoongConfig(ctx android.ModuleContext) GlobalSoongConfig { } } +// The main reason for this Once cache for GlobalSoongConfig is to make the +// dex2oat path available to singletons. In ordinary modules we get it through a +// dex2oatDepTag dependency, but in singletons there's no simple way to do the +// same thing and ensure the right variant is selected, hence this cache to make +// the resolved path available to singletons. This means we depend on there +// being at least one ordinary module with a dex2oatDepTag dependency. +// +// TODO(b/147613152): Implement a way to deal with dependencies from singletons, +// and then possibly remove this cache altogether (but the use in +// GlobalSoongConfigForTests also needs to be rethought). var globalSoongConfigOnceKey = android.NewOnceKey("DexpreoptGlobalSoongConfig") // GetGlobalSoongConfig creates a GlobalSoongConfig the first time it's called, @@ -335,6 +404,14 @@ func GetGlobalSoongConfig(ctx android.ModuleContext) GlobalSoongConfig { globalSoong := ctx.Config().Once(globalSoongConfigOnceKey, func() interface{} { return createGlobalSoongConfig(ctx) }).(GlobalSoongConfig) + + // Always resolve the tool path from the dependency, to ensure that every + // module has the dependency added properly. + myDex2oat := dex2oatPathFromDep(ctx) + if myDex2oat != globalSoong.Dex2oat { + panic(fmt.Sprintf("Inconsistent dex2oat path in cached config: expected %s, got %s", globalSoong.Dex2oat, myDex2oat)) + } + return globalSoong } @@ -382,6 +459,10 @@ func ParseGlobalSoongConfig(ctx android.PathContext, data []byte) (GlobalSoongCo } func (s *globalSoongConfigSingleton) GenerateBuildActions(ctx android.SingletonContext) { + if GetGlobalConfig(ctx).DisablePreopt { + return + } + config := GetCachedGlobalSoongConfig(ctx) jc := globalJsonSoongConfig{ Profman: config.Profman.String(), @@ -409,6 +490,10 @@ func (s *globalSoongConfigSingleton) GenerateBuildActions(ctx android.SingletonC } func (s *globalSoongConfigSingleton) MakeVars(ctx android.MakeVarsContext) { + if GetGlobalConfig(ctx).DisablePreopt { + return + } + config := GetCachedGlobalSoongConfig(ctx) ctx.Strict("DEX2OAT", config.Dex2oat.String()) diff --git a/dexpreopt/testing.go b/dexpreopt/testing.go new file mode 100644 index 000000000..b572eb351 --- /dev/null +++ b/dexpreopt/testing.go @@ -0,0 +1,47 @@ +// 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 dexpreopt + +import ( + "android/soong/android" +) + +type dummyToolBinary struct { + android.ModuleBase +} + +func (m *dummyToolBinary) GenerateAndroidBuildActions(ctx android.ModuleContext) {} + +func (m *dummyToolBinary) HostToolPath() android.OptionalPath { + return android.OptionalPathForPath(android.PathForTesting("dex2oat")) +} + +func dummyToolBinaryFactory() android.Module { + module := &dummyToolBinary{} + android.InitAndroidArchModule(module, android.HostSupported, android.MultilibFirst) + return module +} + +func RegisterToolModulesForTest(ctx *android.TestContext) { + ctx.RegisterModuleType("dummy_tool_binary", dummyToolBinaryFactory) +} + +func BpToolModulesForTest() string { + return ` + dummy_tool_binary { + name: "dex2oatd", + } + ` +} diff --git a/java/app.go b/java/app.go index 9503ec455..f55fc45a1 100755 --- a/java/app.go +++ b/java/app.go @@ -27,6 +27,7 @@ import ( "android/soong/android" "android/soong/cc" + "android/soong/dexpreopt" "android/soong/tradefed" ) @@ -875,6 +876,7 @@ type AndroidAppImport struct { android.ModuleBase android.DefaultableModuleBase prebuilt android.Prebuilt + dexpreopt.DexPreoptModule properties AndroidAppImportProperties dpiVariants interface{} diff --git a/java/java.go b/java/java.go index b20f5f244..2e53654cc 100644 --- a/java/java.go +++ b/java/java.go @@ -76,6 +76,8 @@ func RegisterJavaBuildComponents(ctx android.RegistrationContext) { ctx.RegisterModuleType("java_host_for_device", HostForDeviceFactory) ctx.RegisterModuleType("dex_import", DexImportFactory) + ctx.FinalDepsMutators(dexpreopt.RegisterToolDepsMutator) + ctx.RegisterSingletonType("logtags", LogtagsSingleton) ctx.RegisterSingletonType("kythe_java_extract", kytheExtractJavaFactory) } @@ -369,6 +371,7 @@ type Module struct { android.DefaultableModuleBase android.ApexModuleBase android.SdkBase + dexpreopt.DexPreoptModule properties CompilerProperties protoProperties android.ProtoProperties @@ -1574,6 +1577,16 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) { } } else { outputFile = implementationAndResourcesJar + + // dexpreopt.GetGlobalSoongConfig needs to be called at least once even if + // no module actually is dexpreopted, to ensure there's a cached + // GlobalSoongConfig for the dexpreopt singletons, which will run + // regardless. + // TODO(b/147613152): Remove when the singletons no longer rely on the + // cached GlobalSoongConfig. + if !dexpreopt.GetGlobalConfig(ctx).DisablePreopt { + _ = dexpreopt.GetGlobalSoongConfig(ctx) + } } ctx.CheckbuildFile(outputFile) @@ -2340,6 +2353,7 @@ type Import struct { android.ApexModuleBase prebuilt android.Prebuilt android.SdkBase + dexpreopt.DexPreoptModule properties ImportProperties @@ -2550,6 +2564,7 @@ type DexImport struct { android.DefaultableModuleBase android.ApexModuleBase prebuilt android.Prebuilt + dexpreopt.DexPreoptModule properties DexImportProperties diff --git a/java/java_test.go b/java/java_test.go index 129b17bf7..a2226b59e 100644 --- a/java/java_test.go +++ b/java/java_test.go @@ -57,6 +57,8 @@ func TestMain(m *testing.M) { } func testConfig(env map[string]string, bp string, fs map[string][]byte) android.Config { + bp += dexpreopt.BpToolModulesForTest() + config := TestConfig(buildDir, env, bp, fs) // Set up the global Once cache used for dexpreopt.GlobalSoongConfig, so that @@ -92,6 +94,8 @@ func testContext() *android.TestContext { cc.RegisterRequiredBuildComponentsForTest(ctx) ctx.RegisterModuleType("ndk_prebuilt_shared_stl", cc.NdkPrebuiltSharedStlFactory) + dexpreopt.RegisterToolModulesForTest(ctx) + return ctx } -- cgit v1.2.3-59-g8ed1b From 6d415273c04e5b5fd449b14094c0fe4431b94a43 Mon Sep 17 00:00:00 2001 From: Martin Stjernholm Date: Fri, 31 Jan 2020 17:10:36 +0000 Subject: Do all dexpreoptDisabled checks before registering a dex2oat host dep. Also disable dexpreopting for host. These are necessary to avoid adding dependencies on dex2oat in various non-platform builds where they will break. Since we cannot assume at least one module enables dexpreopting now, the two dexpreopt singletons are silently disabled if there has been no call to dexpreopt.GetGlobalSoongConfig. Bug: 145934348 Bug: 148312086 Bug: 148319588 Bug: 148690468 Test: m Test: env OUT_DIR=out-tools prebuilts/build-tools/build-prebuilts.sh on the aosp-build-tools branch Test: build/soong/soong_ui.bash --make-mode static_sdk_tools dist DIST_DIR=out-dist BUILD_HOST_static=1 on internal (cf b/148312086#comment8) Test: build/soong/soong_ui.bash --make-mode dist DIST_DIR=out-apps TARGET_BUILD_APPS=Launcher3 TARGET_BUILD_VARIANT=userdebug on internal without art/ and external/vixl/ (cf b/148319588) Change-Id: I240dade7204b87fc2d12181534ab23439eca8b46 --- dexpreopt/config.go | 49 +++++++++++++++++++--------------------------- java/app.go | 12 ++++++++---- java/dexpreopt.go | 27 +++++++++++++++++++++---- java/dexpreopt_bootjars.go | 4 ++++ java/java.go | 27 +++++++++++-------------- 5 files changed, 66 insertions(+), 53 deletions(-) (limited to 'java/java.go') diff --git a/dexpreopt/config.go b/dexpreopt/config.go index 3ab341438..98850e51a 100644 --- a/dexpreopt/config.go +++ b/dexpreopt/config.go @@ -317,32 +317,11 @@ var dex2oatDepTag = struct { blueprint.BaseDependencyTag }{} -type DexPreoptModule interface { - dexPreoptModuleSignature() // Not called - only for type detection. -} - -// RegisterToolDepsMutator registers a mutator that adds the necessary -// dependencies to binary modules for tools that are required later when -// Get(Cached)GlobalSoongConfig is called. It should be passed to -// android.RegistrationContext.FinalDepsMutators, and module types that need -// dependencies also need to embed DexPreoptModule. -func RegisterToolDepsMutator(ctx android.RegisterMutatorsContext) { - ctx.BottomUp("dexpreopt_tool_deps", toolDepsMutator).Parallel() -} - -func toolDepsMutator(ctx android.BottomUpMutatorContext) { - if GetGlobalConfig(ctx).DisablePreopt { - // Only register dependencies if dexpreopting is enabled. Necessary to avoid - // them in non-platform builds where dex2oat etc isn't available. - // - // It would be nice to not register this mutator at all then, but - // RegisterMutatorsContext available at registration doesn't have the state - // necessary to pass as PathContext to constructPath etc. - return - } - if _, ok := ctx.Module().(DexPreoptModule); !ok { - return - } +// RegisterToolDeps adds the necessary dependencies to binary modules for tools +// that are required later when Get(Cached)GlobalSoongConfig is called. It +// should be called from a mutator that's registered with +// android.RegistrationContext.FinalDepsMutators. +func RegisterToolDeps(ctx android.BottomUpMutatorContext) { dex2oatBin := dex2oatModuleName(ctx.Config()) v := ctx.Config().BuildOSTarget.Variations() ctx.AddFarVariationDependencies(v, dex2oatDepTag, dex2oatBin) @@ -418,10 +397,13 @@ func GetGlobalSoongConfig(ctx android.ModuleContext) *GlobalSoongConfig { // GetCachedGlobalSoongConfig returns a cached GlobalSoongConfig created by an // earlier GetGlobalSoongConfig call. This function works with any context // compatible with a basic PathContext, since it doesn't try to create a -// GlobalSoongConfig (which requires a full ModuleContext). It will panic if -// called before the first GetGlobalSoongConfig call. +// GlobalSoongConfig with the proper paths (which requires a full +// ModuleContext). If there has been no prior call to GetGlobalSoongConfig, nil +// is returned. func GetCachedGlobalSoongConfig(ctx android.PathContext) *GlobalSoongConfig { - return ctx.Config().Get(globalSoongConfigOnceKey).(*GlobalSoongConfig) + return ctx.Config().Once(globalSoongConfigOnceKey, func() interface{} { + return (*GlobalSoongConfig)(nil) + }).(*GlobalSoongConfig) } type globalJsonSoongConfig struct { @@ -464,6 +446,12 @@ func (s *globalSoongConfigSingleton) GenerateBuildActions(ctx android.SingletonC } config := GetCachedGlobalSoongConfig(ctx) + if config == nil { + // No module has enabled dexpreopting, so we assume there will be no calls + // to dexpreopt_gen. + return + } + jc := globalJsonSoongConfig{ Profman: config.Profman.String(), Dex2oat: config.Dex2oat.String(), @@ -495,6 +483,9 @@ func (s *globalSoongConfigSingleton) MakeVars(ctx android.MakeVarsContext) { } config := GetCachedGlobalSoongConfig(ctx) + if config == nil { + return + } ctx.Strict("DEX2OAT", config.Dex2oat.String()) ctx.Strict("DEXPREOPT_GEN_DEPS", strings.Join([]string{ diff --git a/java/app.go b/java/app.go index f55fc45a1..02f3e7fc0 100755 --- a/java/app.go +++ b/java/app.go @@ -27,7 +27,6 @@ import ( "android/soong/android" "android/soong/cc" - "android/soong/dexpreopt" "android/soong/tradefed" ) @@ -143,6 +142,10 @@ type AndroidApp struct { noticeOutputs android.NoticeOutputs } +func (a *AndroidApp) IsInstallable() bool { + return Bool(a.properties.Installable) +} + func (a *AndroidApp) ExportedProguardFlagFiles() android.Paths { return nil } @@ -339,7 +342,6 @@ func (a *AndroidApp) dexBuildActions(ctx android.ModuleContext) android.Path { installDir = filepath.Join("app", a.installApkName) } a.dexpreopter.installPath = android.PathForModuleInstall(ctx, installDir, a.installApkName+".apk") - a.dexpreopter.isInstallable = Bool(a.properties.Installable) a.dexpreopter.uncompressedDex = a.shouldUncompressDex(ctx) a.dexpreopter.enforceUsesLibs = a.usesLibrary.enforceUsesLibraries() @@ -876,7 +878,6 @@ type AndroidAppImport struct { android.ModuleBase android.DefaultableModuleBase prebuilt android.Prebuilt - dexpreopt.DexPreoptModule properties AndroidAppImportProperties dpiVariants interface{} @@ -924,6 +925,10 @@ type AndroidAppImportProperties struct { Filename *string } +func (a *AndroidAppImport) IsInstallable() bool { + return true +} + // Updates properties with variant-specific values. func (a *AndroidAppImport) processVariants(ctx android.LoadHookContext) { config := ctx.Config() @@ -1066,7 +1071,6 @@ func (a *AndroidAppImport) generateAndroidBuildActions(ctx android.ModuleContext } a.dexpreopter.installPath = installDir.Join(ctx, a.BaseModuleName()+".apk") - a.dexpreopter.isInstallable = true a.dexpreopter.isPresignedPrebuilt = Bool(a.properties.Presigned) a.dexpreopter.uncompressedDex = a.shouldUncompressDex(ctx) diff --git a/java/dexpreopt.go b/java/dexpreopt.go index 2b87cf797..4313964aa 100644 --- a/java/dexpreopt.go +++ b/java/dexpreopt.go @@ -19,6 +19,11 @@ import ( "android/soong/dexpreopt" ) +type dexpreopterInterface interface { + IsInstallable() bool // Structs that embed dexpreopter must implement this. + dexpreoptDisabled(ctx android.BaseModuleContext) bool +} + type dexpreopter struct { dexpreoptProperties DexpreoptProperties @@ -26,7 +31,6 @@ type dexpreopter struct { uncompressedDex bool isSDKLibrary bool isTest bool - isInstallable bool isPresignedPrebuilt bool manifestFile android.Path @@ -58,7 +62,7 @@ type DexpreoptProperties struct { } } -func (d *dexpreopter) dexpreoptDisabled(ctx android.ModuleContext) bool { +func (d *dexpreopter) dexpreoptDisabled(ctx android.BaseModuleContext) bool { global := dexpreopt.GetGlobalConfig(ctx) if global.DisablePreopt { @@ -81,7 +85,11 @@ func (d *dexpreopter) dexpreoptDisabled(ctx android.ModuleContext) bool { return true } - if !d.isInstallable { + if !ctx.Module().(dexpreopterInterface).IsInstallable() { + return true + } + + if ctx.Host() { return true } @@ -95,12 +103,23 @@ func (d *dexpreopter) dexpreoptDisabled(ctx android.ModuleContext) bool { return false } +func dexpreoptToolDepsMutator(ctx android.BottomUpMutatorContext) { + if d, ok := ctx.Module().(dexpreopterInterface); !ok || d.dexpreoptDisabled(ctx) { + return + } + dexpreopt.RegisterToolDeps(ctx) +} + func odexOnSystemOther(ctx android.ModuleContext, installPath android.InstallPath) bool { return dexpreopt.OdexOnSystemOtherByName(ctx.ModuleName(), android.InstallPathToOnDevicePath(ctx, installPath), dexpreopt.GetGlobalConfig(ctx)) } func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.ModuleOutPath) android.ModuleOutPath { - if d.dexpreoptDisabled(ctx) { + // TODO(b/148690468): The check on d.installPath is to bail out in cases where + // the dexpreopter struct hasn't been fully initialized before we're called, + // e.g. in aar.go. This keeps the behaviour that dexpreopting is effectively + // disabled, even if installable is true. + if d.dexpreoptDisabled(ctx) || d.installPath.Base() == "." { return dexJarFile } diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go index 2a2e6dae5..655a47644 100644 --- a/java/dexpreopt_bootjars.go +++ b/java/dexpreopt_bootjars.go @@ -205,6 +205,10 @@ func (d *dexpreoptBootJars) GenerateBuildActions(ctx android.SingletonContext) { if skipDexpreoptBootJars(ctx) { return } + if dexpreopt.GetCachedGlobalSoongConfig(ctx) == nil { + // No module has enabled dexpreopting, so we assume there will be no boot image to make. + return + } d.dexpreoptConfigForMake = android.PathForOutput(ctx, ctx.Config().DeviceName(), "dexpreopt.config") writeGlobalConfigForMake(ctx, d.dexpreoptConfigForMake) diff --git a/java/java.go b/java/java.go index 2e53654cc..ceedd8971 100644 --- a/java/java.go +++ b/java/java.go @@ -76,7 +76,9 @@ func RegisterJavaBuildComponents(ctx android.RegistrationContext) { ctx.RegisterModuleType("java_host_for_device", HostForDeviceFactory) ctx.RegisterModuleType("dex_import", DexImportFactory) - ctx.FinalDepsMutators(dexpreopt.RegisterToolDepsMutator) + ctx.FinalDepsMutators(func(ctx android.RegisterMutatorsContext) { + ctx.BottomUp("dexpreopt_tool_deps", dexpreoptToolDepsMutator).Parallel() + }) ctx.RegisterSingletonType("logtags", LogtagsSingleton) ctx.RegisterSingletonType("kythe_java_extract", kytheExtractJavaFactory) @@ -371,7 +373,6 @@ type Module struct { android.DefaultableModuleBase android.ApexModuleBase android.SdkBase - dexpreopt.DexPreoptModule properties CompilerProperties protoProperties android.ProtoProperties @@ -1577,16 +1578,6 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) { } } else { outputFile = implementationAndResourcesJar - - // dexpreopt.GetGlobalSoongConfig needs to be called at least once even if - // no module actually is dexpreopted, to ensure there's a cached - // GlobalSoongConfig for the dexpreopt singletons, which will run - // regardless. - // TODO(b/147613152): Remove when the singletons no longer rely on the - // cached GlobalSoongConfig. - if !dexpreopt.GetGlobalConfig(ctx).DisablePreopt { - _ = dexpreopt.GetGlobalSoongConfig(ctx) - } } ctx.CheckbuildFile(outputFile) @@ -1794,6 +1785,10 @@ func (j *Module) JacocoReportClassesFile() android.Path { return j.jacocoReportClassesFile } +func (j *Module) IsInstallable() bool { + return Bool(j.properties.Installable) +} + // // Java libraries (.jar file) // @@ -1831,7 +1826,6 @@ func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) { j.checkSdkVersion(ctx) j.dexpreopter.installPath = android.PathForModuleInstall(ctx, "framework", j.Stem()+".jar") j.dexpreopter.isSDKLibrary = j.deviceProperties.IsSDKLibrary - j.dexpreopter.isInstallable = Bool(j.properties.Installable) j.dexpreopter.uncompressedDex = shouldUncompressDex(ctx, &j.dexpreopter) j.deviceProperties.UncompressDex = j.dexpreopter.uncompressedDex j.compile(ctx, nil) @@ -2353,7 +2347,6 @@ type Import struct { android.ApexModuleBase prebuilt android.Prebuilt android.SdkBase - dexpreopt.DexPreoptModule properties ImportProperties @@ -2564,7 +2557,6 @@ type DexImport struct { android.DefaultableModuleBase android.ApexModuleBase prebuilt android.Prebuilt - dexpreopt.DexPreoptModule properties DexImportProperties @@ -2590,13 +2582,16 @@ func (j *DexImport) Stem() string { return proptools.StringDefault(j.properties.Stem, j.ModuleBase.Name()) } +func (j *DexImport) IsInstallable() bool { + return true +} + func (j *DexImport) GenerateAndroidBuildActions(ctx android.ModuleContext) { if len(j.properties.Jars) != 1 { ctx.PropertyErrorf("jars", "exactly one jar must be provided") } j.dexpreopter.installPath = android.PathForModuleInstall(ctx, "framework", j.Stem()+".jar") - j.dexpreopter.isInstallable = true j.dexpreopter.uncompressedDex = shouldUncompressDex(ctx, &j.dexpreopter) inputJar := ctx.ExpandSource(j.properties.Jars[0], "jars") -- cgit v1.2.3-59-g8ed1b