Merge changes from topic "dex2oat-soong-dep" am: cf52e102ce am: fe568ba2a1

Change-Id: Ie691e8f65110d81cf80779600b29a640e2f0588f
This commit is contained in:
Automerger Merge Worker
2020-01-25 03:22:20 +00:00
6 changed files with 165 additions and 10 deletions

View File

@@ -4,6 +4,7 @@ bootstrap_go_package {
srcs: [ srcs: [
"config.go", "config.go",
"dexpreopt.go", "dexpreopt.go",
"testing.go",
], ],
testSrcs: [ testSrcs: [
"dexpreopt_test.go", "dexpreopt_test.go",

View File

@@ -16,8 +16,11 @@ package dexpreopt
import ( import (
"encoding/json" "encoding/json"
"fmt"
"strings" "strings"
"github.com/google/blueprint"
"android/soong/android" "android/soong/android"
) )
@@ -298,6 +301,71 @@ func ParseModuleConfig(ctx android.PathContext, data []byte) (ModuleConfig, erro
return config.ModuleConfig, nil 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. // createGlobalSoongConfig creates a GlobalSoongConfig from the current context.
// Should not be used in dexpreopt_gen. // Should not be used in dexpreopt_gen.
func createGlobalSoongConfig(ctx android.ModuleContext) GlobalSoongConfig { func createGlobalSoongConfig(ctx android.ModuleContext) GlobalSoongConfig {
@@ -308,18 +376,9 @@ func createGlobalSoongConfig(ctx android.ModuleContext) GlobalSoongConfig {
panic("This should not be called from tests. Please call GlobalSoongConfigForTests somewhere in the test setup.") 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{ return GlobalSoongConfig{
Profman: ctx.Config().HostToolPath(ctx, "profman"), Profman: ctx.Config().HostToolPath(ctx, "profman"),
Dex2oat: ctx.Config().HostToolPath(ctx, dex2oatBinary), Dex2oat: dex2oatPathFromDep(ctx),
Aapt: ctx.Config().HostToolPath(ctx, "aapt"), Aapt: ctx.Config().HostToolPath(ctx, "aapt"),
SoongZip: ctx.Config().HostToolPath(ctx, "soong_zip"), SoongZip: ctx.Config().HostToolPath(ctx, "soong_zip"),
Zip2zip: ctx.Config().HostToolPath(ctx, "zip2zip"), Zip2zip: ctx.Config().HostToolPath(ctx, "zip2zip"),
@@ -328,6 +387,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") var globalSoongConfigOnceKey = android.NewOnceKey("DexpreoptGlobalSoongConfig")
// GetGlobalSoongConfig creates a GlobalSoongConfig the first time it's called, // GetGlobalSoongConfig creates a GlobalSoongConfig the first time it's called,
@@ -336,6 +405,14 @@ func GetGlobalSoongConfig(ctx android.ModuleContext) GlobalSoongConfig {
globalSoong := ctx.Config().Once(globalSoongConfigOnceKey, func() interface{} { globalSoong := ctx.Config().Once(globalSoongConfigOnceKey, func() interface{} {
return createGlobalSoongConfig(ctx) return createGlobalSoongConfig(ctx)
}).(GlobalSoongConfig) }).(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 return globalSoong
} }
@@ -383,6 +460,10 @@ func ParseGlobalSoongConfig(ctx android.PathContext, data []byte) (GlobalSoongCo
} }
func (s *globalSoongConfigSingleton) GenerateBuildActions(ctx android.SingletonContext) { func (s *globalSoongConfigSingleton) GenerateBuildActions(ctx android.SingletonContext) {
if GetGlobalConfig(ctx).DisablePreopt {
return
}
config := GetCachedGlobalSoongConfig(ctx) config := GetCachedGlobalSoongConfig(ctx)
jc := globalJsonSoongConfig{ jc := globalJsonSoongConfig{
Profman: config.Profman.String(), Profman: config.Profman.String(),
@@ -410,6 +491,10 @@ func (s *globalSoongConfigSingleton) GenerateBuildActions(ctx android.SingletonC
} }
func (s *globalSoongConfigSingleton) MakeVars(ctx android.MakeVarsContext) { func (s *globalSoongConfigSingleton) MakeVars(ctx android.MakeVarsContext) {
if GetGlobalConfig(ctx).DisablePreopt {
return
}
config := GetCachedGlobalSoongConfig(ctx) config := GetCachedGlobalSoongConfig(ctx)
ctx.Strict("DEX2OAT", config.Dex2oat.String()) ctx.Strict("DEX2OAT", config.Dex2oat.String())

47
dexpreopt/testing.go Normal file
View File

@@ -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",
}
`
}

View File

@@ -27,6 +27,7 @@ import (
"android/soong/android" "android/soong/android"
"android/soong/cc" "android/soong/cc"
"android/soong/dexpreopt"
"android/soong/tradefed" "android/soong/tradefed"
) )
@@ -850,6 +851,7 @@ type AndroidAppImport struct {
android.ModuleBase android.ModuleBase
android.DefaultableModuleBase android.DefaultableModuleBase
prebuilt android.Prebuilt prebuilt android.Prebuilt
dexpreopt.DexPreoptModule
properties AndroidAppImportProperties properties AndroidAppImportProperties
dpiVariants interface{} dpiVariants interface{}

View File

@@ -29,6 +29,7 @@ import (
"github.com/google/blueprint/proptools" "github.com/google/blueprint/proptools"
"android/soong/android" "android/soong/android"
"android/soong/dexpreopt"
"android/soong/java/config" "android/soong/java/config"
"android/soong/tradefed" "android/soong/tradefed"
) )
@@ -79,6 +80,8 @@ func RegisterJavaBuildComponents(ctx android.RegistrationContext) {
ctx.RegisterModuleType("java_host_for_device", HostForDeviceFactory) ctx.RegisterModuleType("java_host_for_device", HostForDeviceFactory)
ctx.RegisterModuleType("dex_import", DexImportFactory) ctx.RegisterModuleType("dex_import", DexImportFactory)
ctx.FinalDepsMutators(dexpreopt.RegisterToolDepsMutator)
ctx.RegisterSingletonType("logtags", LogtagsSingleton) ctx.RegisterSingletonType("logtags", LogtagsSingleton)
ctx.RegisterSingletonType("kythe_java_extract", kytheExtractJavaFactory) ctx.RegisterSingletonType("kythe_java_extract", kytheExtractJavaFactory)
} }
@@ -335,6 +338,7 @@ type Module struct {
android.DefaultableModuleBase android.DefaultableModuleBase
android.ApexModuleBase android.ApexModuleBase
android.SdkBase android.SdkBase
dexpreopt.DexPreoptModule
properties CompilerProperties properties CompilerProperties
protoProperties android.ProtoProperties protoProperties android.ProtoProperties
@@ -1525,6 +1529,16 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
} }
} else { } else {
outputFile = implementationAndResourcesJar 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) ctx.CheckbuildFile(outputFile)
@@ -2275,6 +2289,7 @@ type Import struct {
android.ApexModuleBase android.ApexModuleBase
prebuilt android.Prebuilt prebuilt android.Prebuilt
android.SdkBase android.SdkBase
dexpreopt.DexPreoptModule
properties ImportProperties properties ImportProperties
@@ -2477,6 +2492,7 @@ type DexImport struct {
android.DefaultableModuleBase android.DefaultableModuleBase
android.ApexModuleBase android.ApexModuleBase
prebuilt android.Prebuilt prebuilt android.Prebuilt
dexpreopt.DexPreoptModule
properties DexImportProperties properties DexImportProperties

View File

@@ -57,6 +57,8 @@ func TestMain(m *testing.M) {
} }
func testConfig(env map[string]string, bp string, fs map[string][]byte) android.Config { func testConfig(env map[string]string, bp string, fs map[string][]byte) android.Config {
bp += dexpreopt.BpToolModulesForTest()
config := TestConfig(buildDir, env, bp, fs) config := TestConfig(buildDir, env, bp, fs)
// Set up the global Once cache used for dexpreopt.GlobalSoongConfig, so that // Set up the global Once cache used for dexpreopt.GlobalSoongConfig, so that
@@ -92,6 +94,8 @@ func testContext() *android.TestContext {
cc.RegisterRequiredBuildComponentsForTest(ctx) cc.RegisterRequiredBuildComponentsForTest(ctx)
ctx.RegisterModuleType("ndk_prebuilt_shared_stl", cc.NdkPrebuiltSharedStlFactory) ctx.RegisterModuleType("ndk_prebuilt_shared_stl", cc.NdkPrebuiltSharedStlFactory)
dexpreopt.RegisterToolModulesForTest(ctx)
return ctx return ctx
} }