Merge changes from topic "dex2oat-soong-dep-2"
* changes: Do all dexpreoptDisabled checks before registering a dex2oat host dep. Pass dexpreopt config structs by reference. Reland: Get the dex2oat host tool path from module dependency on the binary module. Reland: Move the Once cache for dexpreopt.GlobalConfig into the dexpreopt package. Reland: Separate dexpreopt.GlobalSoongConfig to allow independent caching of it.
This commit is contained in:
commit
c9f9ab89a9
|
@ -4,6 +4,7 @@ bootstrap_go_package {
|
|||
srcs: [
|
||||
"config.go",
|
||||
"dexpreopt.go",
|
||||
"testing.go",
|
||||
],
|
||||
testSrcs: [
|
||||
"dexpreopt_test.go",
|
||||
|
|
|
@ -16,14 +16,16 @@ package dexpreopt
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/google/blueprint"
|
||||
|
||||
"android/soong/android"
|
||||
)
|
||||
|
||||
// GlobalConfig stores the configuration for dex preopting. The fields are set
|
||||
// from product variables via dex_preopt_config.mk, except for SoongConfig
|
||||
// which come from CreateGlobalSoongConfig.
|
||||
// from product variables via dex_preopt_config.mk.
|
||||
type GlobalConfig struct {
|
||||
DisablePreopt bool // disable preopt for all modules
|
||||
DisablePreoptModules []string // modules with preopt disabled by product-specific config
|
||||
|
@ -81,8 +83,6 @@ type GlobalConfig struct {
|
|||
BootFlags string // extra flags to pass to dex2oat for the boot image
|
||||
Dex2oatImageXmx string // max heap size for dex2oat for the boot image
|
||||
Dex2oatImageXms string // initial heap size for dex2oat for the boot image
|
||||
|
||||
SoongConfig GlobalSoongConfig // settings read from dexpreopt_soong.config
|
||||
}
|
||||
|
||||
// GlobalSoongConfig contains the global config that is generated from Soong,
|
||||
|
@ -178,14 +178,11 @@ func constructWritablePath(ctx android.PathContext, path string) android.Writabl
|
|||
return constructPath(ctx, path).(android.WritablePath)
|
||||
}
|
||||
|
||||
// LoadGlobalConfig reads the global dexpreopt.config file into a GlobalConfig
|
||||
// struct, except the SoongConfig field which is set from the provided
|
||||
// soongConfig argument. LoadGlobalConfig is used directly in Soong and in
|
||||
// dexpreopt_gen called from Make to read the $OUT/dexpreopt.config written by
|
||||
// Make.
|
||||
func LoadGlobalConfig(ctx android.PathContext, data []byte, soongConfig GlobalSoongConfig) (GlobalConfig, error) {
|
||||
// ParseGlobalConfig parses the given data assumed to be read from the global
|
||||
// dexpreopt.config file into a GlobalConfig struct.
|
||||
func ParseGlobalConfig(ctx android.PathContext, data []byte) (*GlobalConfig, error) {
|
||||
type GlobalJSONConfig struct {
|
||||
GlobalConfig
|
||||
*GlobalConfig
|
||||
|
||||
// Copies of entries in GlobalConfig that are not constructable without extra parameters. They will be
|
||||
// used to construct the real value manually below.
|
||||
|
@ -203,19 +200,70 @@ func LoadGlobalConfig(ctx android.PathContext, data []byte, soongConfig GlobalSo
|
|||
config.GlobalConfig.DirtyImageObjects = android.OptionalPathForPath(constructPath(ctx, config.DirtyImageObjects))
|
||||
config.GlobalConfig.BootImageProfiles = constructPaths(ctx, config.BootImageProfiles)
|
||||
|
||||
// Set this here to force the caller to provide a value for this struct (from
|
||||
// either CreateGlobalSoongConfig or LoadGlobalSoongConfig).
|
||||
config.GlobalConfig.SoongConfig = soongConfig
|
||||
|
||||
return config.GlobalConfig, nil
|
||||
}
|
||||
|
||||
// LoadModuleConfig reads a per-module dexpreopt.config file into a ModuleConfig struct. It is not used in Soong, which
|
||||
// receives a ModuleConfig struct directly from java/dexpreopt.go. It is used in dexpreopt_gen called from oMake to
|
||||
// read the module dexpreopt.config written by Make.
|
||||
func LoadModuleConfig(ctx android.PathContext, data []byte) (ModuleConfig, error) {
|
||||
type globalConfigAndRaw struct {
|
||||
global *GlobalConfig
|
||||
data []byte
|
||||
}
|
||||
|
||||
// GetGlobalConfig returns the global dexpreopt.config that's created in the
|
||||
// make config phase. It is loaded once the first time it is called for any
|
||||
// ctx.Config(), and returns the same data for all future calls with the same
|
||||
// ctx.Config(). A value can be inserted for tests using
|
||||
// setDexpreoptTestGlobalConfig.
|
||||
func GetGlobalConfig(ctx android.PathContext) *GlobalConfig {
|
||||
return getGlobalConfigRaw(ctx).global
|
||||
}
|
||||
|
||||
// GetGlobalConfigRawData is the same as GetGlobalConfig, except that it returns
|
||||
// the literal content of dexpreopt.config.
|
||||
func GetGlobalConfigRawData(ctx android.PathContext) []byte {
|
||||
return getGlobalConfigRaw(ctx).data
|
||||
}
|
||||
|
||||
var globalConfigOnceKey = android.NewOnceKey("DexpreoptGlobalConfig")
|
||||
var testGlobalConfigOnceKey = android.NewOnceKey("TestDexpreoptGlobalConfig")
|
||||
|
||||
func getGlobalConfigRaw(ctx android.PathContext) globalConfigAndRaw {
|
||||
return ctx.Config().Once(globalConfigOnceKey, func() interface{} {
|
||||
if data, err := ctx.Config().DexpreoptGlobalConfig(ctx); err != nil {
|
||||
panic(err)
|
||||
} else if data != nil {
|
||||
globalConfig, err := ParseGlobalConfig(ctx, data)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return globalConfigAndRaw{globalConfig, data}
|
||||
}
|
||||
|
||||
// No global config filename set, see if there is a test config set
|
||||
return ctx.Config().Once(testGlobalConfigOnceKey, func() interface{} {
|
||||
// Nope, return a config with preopting disabled
|
||||
return globalConfigAndRaw{&GlobalConfig{
|
||||
DisablePreopt: true,
|
||||
DisableGenerateProfile: true,
|
||||
}, nil}
|
||||
})
|
||||
}).(globalConfigAndRaw)
|
||||
}
|
||||
|
||||
// SetTestGlobalConfig sets a GlobalConfig that future calls to GetGlobalConfig
|
||||
// will return. It must be called before the first call to GetGlobalConfig for
|
||||
// the config.
|
||||
func SetTestGlobalConfig(config android.Config, globalConfig *GlobalConfig) {
|
||||
config.Once(testGlobalConfigOnceKey, func() interface{} { return globalConfigAndRaw{globalConfig, nil} })
|
||||
}
|
||||
|
||||
// ParseModuleConfig parses a per-module dexpreopt.config file into a
|
||||
// ModuleConfig struct. It is not used in Soong, which receives a ModuleConfig
|
||||
// struct directly from java/dexpreopt.go. It is used in dexpreopt_gen called
|
||||
// from Make to read the module dexpreopt.config written in the Make config
|
||||
// stage.
|
||||
func ParseModuleConfig(ctx android.PathContext, data []byte) (*ModuleConfig, error) {
|
||||
type ModuleJSONConfig struct {
|
||||
ModuleConfig
|
||||
*ModuleConfig
|
||||
|
||||
// Copies of entries in ModuleConfig that are not constructable without extra parameters. They will be
|
||||
// used to construct the real value manually below.
|
||||
|
@ -252,21 +300,63 @@ func LoadModuleConfig(ctx android.PathContext, data []byte) (ModuleConfig, error
|
|||
return config.ModuleConfig, nil
|
||||
}
|
||||
|
||||
// CreateGlobalSoongConfig creates a GlobalSoongConfig from the current context.
|
||||
// Should not be used in dexpreopt_gen.
|
||||
func CreateGlobalSoongConfig(ctx android.PathContext) GlobalSoongConfig {
|
||||
// Default to debug version to help find bugs.
|
||||
// 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.
|
||||
var dex2oatBinary string
|
||||
if ctx.Config().Getenv("USE_DEX2OAT_DEBUG") == "false" {
|
||||
dex2oatBinary = "dex2oat"
|
||||
if config.Getenv("USE_DEX2OAT_DEBUG") == "false" {
|
||||
return "dex2oat"
|
||||
} else {
|
||||
dex2oatBinary = "dex2oatd"
|
||||
return "dex2oatd"
|
||||
}
|
||||
}
|
||||
|
||||
var dex2oatDepTag = struct {
|
||||
blueprint.BaseDependencyTag
|
||||
}{}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
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))
|
||||
}
|
||||
|
||||
return GlobalSoongConfig{
|
||||
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 {
|
||||
if ctx.Config().TestProductVariables != nil {
|
||||
// If we're called in a test there'll be a confusing error from the path
|
||||
// functions below that gets reported without a stack trace, so let's panic
|
||||
// properly with a more helpful message.
|
||||
panic("This should not be called from tests. Please call GlobalSoongConfigForTests somewhere in the test setup.")
|
||||
}
|
||||
|
||||
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"),
|
||||
|
@ -275,6 +365,47 @@ func CreateGlobalSoongConfig(ctx android.PathContext) 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,
|
||||
// and later returns the same cached instance.
|
||||
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
|
||||
}
|
||||
|
||||
// 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 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().Once(globalSoongConfigOnceKey, func() interface{} {
|
||||
return (*GlobalSoongConfig)(nil)
|
||||
}).(*GlobalSoongConfig)
|
||||
}
|
||||
|
||||
type globalJsonSoongConfig struct {
|
||||
Profman string
|
||||
Dex2oat string
|
||||
|
@ -285,17 +416,18 @@ type globalJsonSoongConfig struct {
|
|||
ConstructContext string
|
||||
}
|
||||
|
||||
// LoadGlobalSoongConfig reads the dexpreopt_soong.config file into a
|
||||
// GlobalSoongConfig struct. It is only used in dexpreopt_gen.
|
||||
func LoadGlobalSoongConfig(ctx android.PathContext, data []byte) (GlobalSoongConfig, error) {
|
||||
// ParseGlobalSoongConfig parses the given data assumed to be read from the
|
||||
// global dexpreopt_soong.config file into a GlobalSoongConfig struct. It is
|
||||
// only used in dexpreopt_gen.
|
||||
func ParseGlobalSoongConfig(ctx android.PathContext, data []byte) (*GlobalSoongConfig, error) {
|
||||
var jc globalJsonSoongConfig
|
||||
|
||||
err := json.Unmarshal(data, &jc)
|
||||
if err != nil {
|
||||
return GlobalSoongConfig{}, err
|
||||
return &GlobalSoongConfig{}, err
|
||||
}
|
||||
|
||||
config := GlobalSoongConfig{
|
||||
config := &GlobalSoongConfig{
|
||||
Profman: constructPath(ctx, jc.Profman),
|
||||
Dex2oat: constructPath(ctx, jc.Dex2oat),
|
||||
Aapt: constructPath(ctx, jc.Aapt),
|
||||
|
@ -309,7 +441,17 @@ func LoadGlobalSoongConfig(ctx android.PathContext, data []byte) (GlobalSoongCon
|
|||
}
|
||||
|
||||
func (s *globalSoongConfigSingleton) GenerateBuildActions(ctx android.SingletonContext) {
|
||||
config := CreateGlobalSoongConfig(ctx)
|
||||
if GetGlobalConfig(ctx).DisablePreopt {
|
||||
return
|
||||
}
|
||||
|
||||
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(),
|
||||
|
@ -336,7 +478,14 @@ func (s *globalSoongConfigSingleton) GenerateBuildActions(ctx android.SingletonC
|
|||
}
|
||||
|
||||
func (s *globalSoongConfigSingleton) MakeVars(ctx android.MakeVarsContext) {
|
||||
config := CreateGlobalSoongConfig(ctx)
|
||||
if GetGlobalConfig(ctx).DisablePreopt {
|
||||
return
|
||||
}
|
||||
|
||||
config := GetCachedGlobalSoongConfig(ctx)
|
||||
if config == nil {
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Strict("DEX2OAT", config.Dex2oat.String())
|
||||
ctx.Strict("DEXPREOPT_GEN_DEPS", strings.Join([]string{
|
||||
|
@ -350,8 +499,8 @@ func (s *globalSoongConfigSingleton) MakeVars(ctx android.MakeVarsContext) {
|
|||
}, " "))
|
||||
}
|
||||
|
||||
func GlobalConfigForTests(ctx android.PathContext) GlobalConfig {
|
||||
return GlobalConfig{
|
||||
func GlobalConfigForTests(ctx android.PathContext) *GlobalConfig {
|
||||
return &GlobalConfig{
|
||||
DisablePreopt: false,
|
||||
DisablePreoptModules: nil,
|
||||
OnlyPreoptBootImageAndSystemServer: false,
|
||||
|
@ -389,7 +538,14 @@ func GlobalConfigForTests(ctx android.PathContext) GlobalConfig {
|
|||
BootFlags: "",
|
||||
Dex2oatImageXmx: "",
|
||||
Dex2oatImageXms: "",
|
||||
SoongConfig: GlobalSoongConfig{
|
||||
}
|
||||
}
|
||||
|
||||
func GlobalSoongConfigForTests(config android.Config) *GlobalSoongConfig {
|
||||
// Install the test GlobalSoongConfig in the Once cache so that later calls to
|
||||
// Get(Cached)GlobalSoongConfig returns it without trying to create a real one.
|
||||
return config.Once(globalSoongConfigOnceKey, func() interface{} {
|
||||
return &GlobalSoongConfig{
|
||||
Profman: android.PathForTesting("profman"),
|
||||
Dex2oat: android.PathForTesting("dex2oat"),
|
||||
Aapt: android.PathForTesting("aapt"),
|
||||
|
@ -397,6 +553,6 @@ func GlobalConfigForTests(ctx android.PathContext) GlobalConfig {
|
|||
Zip2zip: android.PathForTesting("zip2zip"),
|
||||
ManifestCheck: android.PathForTesting("manifest_check"),
|
||||
ConstructContext: android.PathForTesting("construct_context.sh"),
|
||||
},
|
||||
}
|
||||
}
|
||||
}).(*GlobalSoongConfig)
|
||||
}
|
||||
|
|
|
@ -58,8 +58,8 @@ var SystemServerForcedDepTag = dependencyTag{name: "system-server-forced-dep"}
|
|||
|
||||
// GenerateDexpreoptRule generates a set of commands that will preopt a module based on a GlobalConfig and a
|
||||
// ModuleConfig. The produced files and their install locations will be available through rule.Installs().
|
||||
func GenerateDexpreoptRule(ctx android.PathContext,
|
||||
global GlobalConfig, module ModuleConfig) (rule *android.RuleBuilder, err error) {
|
||||
func GenerateDexpreoptRule(ctx android.PathContext, globalSoong *GlobalSoongConfig,
|
||||
global *GlobalConfig, module *ModuleConfig) (rule *android.RuleBuilder, err error) {
|
||||
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
|
@ -81,10 +81,10 @@ func GenerateDexpreoptRule(ctx android.PathContext,
|
|||
|
||||
var profile android.WritablePath
|
||||
if generateProfile {
|
||||
profile = profileCommand(ctx, global, module, rule)
|
||||
profile = profileCommand(ctx, globalSoong, global, module, rule)
|
||||
}
|
||||
if generateBootProfile {
|
||||
bootProfileCommand(ctx, global, module, rule)
|
||||
bootProfileCommand(ctx, globalSoong, global, module, rule)
|
||||
}
|
||||
|
||||
if !dexpreoptDisabled(ctx, global, module) {
|
||||
|
@ -96,7 +96,7 @@ func GenerateDexpreoptRule(ctx android.PathContext,
|
|||
generateDM := shouldGenerateDM(module, global)
|
||||
|
||||
for archIdx, _ := range module.Archs {
|
||||
dexpreoptCommand(ctx, global, module, rule, archIdx, profile, appImage, generateDM)
|
||||
dexpreoptCommand(ctx, globalSoong, global, module, rule, archIdx, profile, appImage, generateDM)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -104,7 +104,7 @@ func GenerateDexpreoptRule(ctx android.PathContext,
|
|||
return rule, nil
|
||||
}
|
||||
|
||||
func dexpreoptDisabled(ctx android.PathContext, global GlobalConfig, module ModuleConfig) bool {
|
||||
func dexpreoptDisabled(ctx android.PathContext, global *GlobalConfig, module *ModuleConfig) bool {
|
||||
if contains(global.DisablePreoptModules, module.Name) {
|
||||
return true
|
||||
}
|
||||
|
@ -135,8 +135,8 @@ func dexpreoptDisabled(ctx android.PathContext, global GlobalConfig, module Modu
|
|||
return false
|
||||
}
|
||||
|
||||
func profileCommand(ctx android.PathContext, global GlobalConfig, module ModuleConfig,
|
||||
rule *android.RuleBuilder) android.WritablePath {
|
||||
func profileCommand(ctx android.PathContext, globalSoong *GlobalSoongConfig, global *GlobalConfig,
|
||||
module *ModuleConfig, rule *android.RuleBuilder) android.WritablePath {
|
||||
|
||||
profilePath := module.BuildPath.InSameDir(ctx, "profile.prof")
|
||||
profileInstalledPath := module.DexLocation + ".prof"
|
||||
|
@ -147,7 +147,7 @@ func profileCommand(ctx android.PathContext, global GlobalConfig, module ModuleC
|
|||
|
||||
cmd := rule.Command().
|
||||
Text(`ANDROID_LOG_TAGS="*:e"`).
|
||||
Tool(global.SoongConfig.Profman)
|
||||
Tool(globalSoong.Profman)
|
||||
|
||||
if module.ProfileIsTextListing {
|
||||
// The profile is a test listing of classes (used for framework jars).
|
||||
|
@ -174,8 +174,8 @@ func profileCommand(ctx android.PathContext, global GlobalConfig, module ModuleC
|
|||
return profilePath
|
||||
}
|
||||
|
||||
func bootProfileCommand(ctx android.PathContext, global GlobalConfig, module ModuleConfig,
|
||||
rule *android.RuleBuilder) android.WritablePath {
|
||||
func bootProfileCommand(ctx android.PathContext, globalSoong *GlobalSoongConfig, global *GlobalConfig,
|
||||
module *ModuleConfig, rule *android.RuleBuilder) android.WritablePath {
|
||||
|
||||
profilePath := module.BuildPath.InSameDir(ctx, "profile.bprof")
|
||||
profileInstalledPath := module.DexLocation + ".bprof"
|
||||
|
@ -186,7 +186,7 @@ func bootProfileCommand(ctx android.PathContext, global GlobalConfig, module Mod
|
|||
|
||||
cmd := rule.Command().
|
||||
Text(`ANDROID_LOG_TAGS="*:e"`).
|
||||
Tool(global.SoongConfig.Profman)
|
||||
Tool(globalSoong.Profman)
|
||||
|
||||
// The profile is a test listing of methods.
|
||||
// We need to generate the actual binary profile.
|
||||
|
@ -206,8 +206,9 @@ func bootProfileCommand(ctx android.PathContext, global GlobalConfig, module Mod
|
|||
return profilePath
|
||||
}
|
||||
|
||||
func dexpreoptCommand(ctx android.PathContext, global GlobalConfig, module ModuleConfig, rule *android.RuleBuilder,
|
||||
archIdx int, profile android.WritablePath, appImage bool, generateDM bool) {
|
||||
func dexpreoptCommand(ctx android.PathContext, globalSoong *GlobalSoongConfig, global *GlobalConfig,
|
||||
module *ModuleConfig, rule *android.RuleBuilder, archIdx int, profile android.WritablePath,
|
||||
appImage bool, generateDM bool) {
|
||||
|
||||
arch := module.Archs[archIdx]
|
||||
|
||||
|
@ -345,14 +346,14 @@ func dexpreoptCommand(ctx android.PathContext, global GlobalConfig, module Modul
|
|||
if module.EnforceUsesLibraries {
|
||||
if module.ManifestPath != nil {
|
||||
rule.Command().Text(`target_sdk_version="$(`).
|
||||
Tool(global.SoongConfig.ManifestCheck).
|
||||
Tool(globalSoong.ManifestCheck).
|
||||
Flag("--extract-target-sdk-version").
|
||||
Input(module.ManifestPath).
|
||||
Text(`)"`)
|
||||
} else {
|
||||
// No manifest to extract targetSdkVersion from, hope that DexJar is an APK
|
||||
rule.Command().Text(`target_sdk_version="$(`).
|
||||
Tool(global.SoongConfig.Aapt).
|
||||
Tool(globalSoong.Aapt).
|
||||
Flag("dump badging").
|
||||
Input(module.DexPath).
|
||||
Text(`| grep "targetSdkVersion" | sed -n "s/targetSdkVersion:'\(.*\)'/\1/p"`).
|
||||
|
@ -373,7 +374,7 @@ func dexpreoptCommand(ctx android.PathContext, global GlobalConfig, module Modul
|
|||
Implicits(conditionalClassLoaderContextHost29)
|
||||
rule.Command().Textf(`conditional_target_libs_29="%s"`,
|
||||
strings.Join(conditionalClassLoaderContextTarget29, " "))
|
||||
rule.Command().Text("source").Tool(global.SoongConfig.ConstructContext).Input(module.DexPath)
|
||||
rule.Command().Text("source").Tool(globalSoong.ConstructContext).Input(module.DexPath)
|
||||
}
|
||||
|
||||
// Devices that do not have a product partition use a symlink from /product to /system/product.
|
||||
|
@ -386,7 +387,7 @@ func dexpreoptCommand(ctx android.PathContext, global GlobalConfig, module Modul
|
|||
|
||||
cmd := rule.Command().
|
||||
Text(`ANDROID_LOG_TAGS="*:e"`).
|
||||
Tool(global.SoongConfig.Dex2oat).
|
||||
Tool(globalSoong.Dex2oat).
|
||||
Flag("--avoid-storing-invocation").
|
||||
FlagWithOutput("--write-invocation-to=", invocationPath).ImplicitOutput(invocationPath).
|
||||
Flag("--runtime-arg").FlagWithArg("-Xms", global.Dex2oatXms).
|
||||
|
@ -455,7 +456,7 @@ func dexpreoptCommand(ctx android.PathContext, global GlobalConfig, module Modul
|
|||
dmInstalledPath := pathtools.ReplaceExtension(module.DexLocation, "dm")
|
||||
tmpPath := module.BuildPath.InSameDir(ctx, "primary.vdex")
|
||||
rule.Command().Text("cp -f").Input(vdexPath).Output(tmpPath)
|
||||
rule.Command().Tool(global.SoongConfig.SoongZip).
|
||||
rule.Command().Tool(globalSoong.SoongZip).
|
||||
FlagWithArg("-L", "9").
|
||||
FlagWithOutput("-o", dmPath).
|
||||
Flag("-j").
|
||||
|
@ -520,14 +521,14 @@ func dexpreoptCommand(ctx android.PathContext, global GlobalConfig, module Modul
|
|||
rule.Install(vdexPath, vdexInstallPath)
|
||||
}
|
||||
|
||||
func shouldGenerateDM(module ModuleConfig, global GlobalConfig) bool {
|
||||
func shouldGenerateDM(module *ModuleConfig, global *GlobalConfig) bool {
|
||||
// Generating DM files only makes sense for verify, avoid doing for non verify compiler filter APKs.
|
||||
// No reason to use a dm file if the dex is already uncompressed.
|
||||
return global.GenerateDMFiles && !module.UncompressedDex &&
|
||||
contains(module.PreoptFlags, "--compiler-filter=verify")
|
||||
}
|
||||
|
||||
func OdexOnSystemOtherByName(name string, dexLocation string, global GlobalConfig) bool {
|
||||
func OdexOnSystemOtherByName(name string, dexLocation string, global *GlobalConfig) bool {
|
||||
if !global.HasSystemOther {
|
||||
return false
|
||||
}
|
||||
|
@ -549,7 +550,7 @@ func OdexOnSystemOtherByName(name string, dexLocation string, global GlobalConfi
|
|||
return false
|
||||
}
|
||||
|
||||
func odexOnSystemOther(module ModuleConfig, global GlobalConfig) bool {
|
||||
func odexOnSystemOther(module *ModuleConfig, global *GlobalConfig) bool {
|
||||
return OdexOnSystemOtherByName(module.Name, module.DexLocation, global)
|
||||
}
|
||||
|
||||
|
@ -562,7 +563,7 @@ func PathToLocation(path android.Path, arch android.ArchType) string {
|
|||
return filepath.Join(filepath.Dir(filepath.Dir(path.String())), filepath.Base(path.String()))
|
||||
}
|
||||
|
||||
func pathForLibrary(module ModuleConfig, lib string) android.Path {
|
||||
func pathForLibrary(module *ModuleConfig, lib string) android.Path {
|
||||
path, ok := module.LibraryPaths[lib]
|
||||
if !ok {
|
||||
panic(fmt.Errorf("unknown library path for %q", lib))
|
||||
|
@ -601,7 +602,7 @@ var nonUpdatableSystemServerJarsKey = android.NewOnceKey("nonUpdatableSystemServ
|
|||
|
||||
// TODO: eliminate the superficial global config parameter by moving global config definition
|
||||
// from java subpackage to dexpreopt.
|
||||
func NonUpdatableSystemServerJars(ctx android.PathContext, global GlobalConfig) []string {
|
||||
func NonUpdatableSystemServerJars(ctx android.PathContext, global *GlobalConfig) []string {
|
||||
return ctx.Config().Once(nonUpdatableSystemServerJarsKey, func() interface{} {
|
||||
return android.RemoveListFromList(global.SystemServerJars,
|
||||
GetJarsFromApexJarPairs(global.UpdatableSystemServerJars))
|
||||
|
|
|
@ -80,13 +80,13 @@ func main() {
|
|||
|
||||
globalSoongConfigData, err := ioutil.ReadFile(*globalSoongConfigPath)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "error reading global config %q: %s\n", *globalSoongConfigPath, err)
|
||||
fmt.Fprintf(os.Stderr, "error reading global Soong config %q: %s\n", *globalSoongConfigPath, err)
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
globalSoongConfig, err := dexpreopt.LoadGlobalSoongConfig(ctx, globalSoongConfigData)
|
||||
globalSoongConfig, err := dexpreopt.ParseGlobalSoongConfig(ctx, globalSoongConfigData)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "error loading global config %q: %s\n", *globalSoongConfigPath, err)
|
||||
fmt.Fprintf(os.Stderr, "error parsing global Soong config %q: %s\n", *globalSoongConfigPath, err)
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
|
@ -96,9 +96,9 @@ func main() {
|
|||
os.Exit(2)
|
||||
}
|
||||
|
||||
globalConfig, err := dexpreopt.LoadGlobalConfig(ctx, globalConfigData, globalSoongConfig)
|
||||
globalConfig, err := dexpreopt.ParseGlobalConfig(ctx, globalConfigData)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "error parse global config %q: %s\n", *globalConfigPath, err)
|
||||
fmt.Fprintf(os.Stderr, "error parsing global config %q: %s\n", *globalConfigPath, err)
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
|
@ -108,9 +108,9 @@ func main() {
|
|||
os.Exit(2)
|
||||
}
|
||||
|
||||
moduleConfig, err := dexpreopt.LoadModuleConfig(ctx, moduleConfigData)
|
||||
moduleConfig, err := dexpreopt.ParseModuleConfig(ctx, moduleConfigData)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "error loading module config %q: %s\n", *moduleConfigPath, err)
|
||||
fmt.Fprintf(os.Stderr, "error parsing module config %q: %s\n", *moduleConfigPath, err)
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
|
@ -130,12 +130,12 @@ func main() {
|
|||
}
|
||||
}()
|
||||
|
||||
writeScripts(ctx, globalConfig, moduleConfig, *dexpreoptScriptPath)
|
||||
writeScripts(ctx, globalSoongConfig, globalConfig, moduleConfig, *dexpreoptScriptPath)
|
||||
}
|
||||
|
||||
func writeScripts(ctx android.PathContext, global dexpreopt.GlobalConfig, module dexpreopt.ModuleConfig,
|
||||
dexpreoptScriptPath string) {
|
||||
dexpreoptRule, err := dexpreopt.GenerateDexpreoptRule(ctx, global, module)
|
||||
func writeScripts(ctx android.PathContext, globalSoong *dexpreopt.GlobalSoongConfig,
|
||||
global *dexpreopt.GlobalConfig, module *dexpreopt.ModuleConfig, dexpreoptScriptPath string) {
|
||||
dexpreoptRule, err := dexpreopt.GenerateDexpreoptRule(ctx, globalSoong, global, module)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
@ -150,7 +150,7 @@ func writeScripts(ctx android.PathContext, global dexpreopt.GlobalConfig, module
|
|||
dexpreoptRule.Command().Text("mkdir -p").Flag(filepath.Dir(installPath.String()))
|
||||
dexpreoptRule.Command().Text("cp -f").Input(install.From).Output(installPath)
|
||||
}
|
||||
dexpreoptRule.Command().Tool(global.SoongConfig.SoongZip).
|
||||
dexpreoptRule.Command().Tool(globalSoong.SoongZip).
|
||||
FlagWithArg("-o ", "$2").
|
||||
FlagWithArg("-C ", installDir.String()).
|
||||
FlagWithArg("-D ", installDir.String())
|
||||
|
|
|
@ -20,20 +20,20 @@ import (
|
|||
"testing"
|
||||
)
|
||||
|
||||
func testSystemModuleConfig(ctx android.PathContext, name string) ModuleConfig {
|
||||
func testSystemModuleConfig(ctx android.PathContext, name string) *ModuleConfig {
|
||||
return testModuleConfig(ctx, name, "system")
|
||||
}
|
||||
|
||||
func testSystemProductModuleConfig(ctx android.PathContext, name string) ModuleConfig {
|
||||
func testSystemProductModuleConfig(ctx android.PathContext, name string) *ModuleConfig {
|
||||
return testModuleConfig(ctx, name, "system/product")
|
||||
}
|
||||
|
||||
func testProductModuleConfig(ctx android.PathContext, name string) ModuleConfig {
|
||||
func testProductModuleConfig(ctx android.PathContext, name string) *ModuleConfig {
|
||||
return testModuleConfig(ctx, name, "product")
|
||||
}
|
||||
|
||||
func testModuleConfig(ctx android.PathContext, name, partition string) ModuleConfig {
|
||||
return ModuleConfig{
|
||||
func testModuleConfig(ctx android.PathContext, name, partition string) *ModuleConfig {
|
||||
return &ModuleConfig{
|
||||
Name: name,
|
||||
DexLocation: fmt.Sprintf("/%s/app/test/%s.apk", partition, name),
|
||||
BuildPath: android.PathForOutput(ctx, fmt.Sprintf("%s/%s.apk", name, name)),
|
||||
|
@ -61,10 +61,13 @@ func testModuleConfig(ctx android.PathContext, name, partition string) ModuleCon
|
|||
}
|
||||
|
||||
func TestDexPreopt(t *testing.T) {
|
||||
ctx := android.PathContextForTesting(android.TestConfig("out", nil, "", nil))
|
||||
global, module := GlobalConfigForTests(ctx), testSystemModuleConfig(ctx, "test")
|
||||
config := android.TestConfig("out", nil, "", nil)
|
||||
ctx := android.PathContextForTesting(config)
|
||||
globalSoong := GlobalSoongConfigForTests(config)
|
||||
global := GlobalConfigForTests(ctx)
|
||||
module := testSystemModuleConfig(ctx, "test")
|
||||
|
||||
rule, err := GenerateDexpreoptRule(ctx, global, module)
|
||||
rule, err := GenerateDexpreoptRule(ctx, globalSoong, global, module)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -80,7 +83,9 @@ func TestDexPreopt(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestDexPreoptSystemOther(t *testing.T) {
|
||||
ctx := android.PathContextForTesting(android.TestConfig("out", nil, "", nil))
|
||||
config := android.TestConfig("out", nil, "", nil)
|
||||
ctx := android.PathContextForTesting(config)
|
||||
globalSoong := GlobalSoongConfigForTests(config)
|
||||
global := GlobalConfigForTests(ctx)
|
||||
systemModule := testSystemModuleConfig(ctx, "Stest")
|
||||
systemProductModule := testSystemProductModuleConfig(ctx, "SPtest")
|
||||
|
@ -89,7 +94,7 @@ func TestDexPreoptSystemOther(t *testing.T) {
|
|||
global.HasSystemOther = true
|
||||
|
||||
type moduleTest struct {
|
||||
module ModuleConfig
|
||||
module *ModuleConfig
|
||||
expectedPartition string
|
||||
}
|
||||
tests := []struct {
|
||||
|
@ -118,7 +123,7 @@ func TestDexPreoptSystemOther(t *testing.T) {
|
|||
for _, test := range tests {
|
||||
global.PatternsOnSystemOther = test.patterns
|
||||
for _, mt := range test.moduleTests {
|
||||
rule, err := GenerateDexpreoptRule(ctx, global, mt.module)
|
||||
rule, err := GenerateDexpreoptRule(ctx, globalSoong, global, mt.module)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -138,12 +143,15 @@ func TestDexPreoptSystemOther(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestDexPreoptProfile(t *testing.T) {
|
||||
ctx := android.PathContextForTesting(android.TestConfig("out", nil, "", nil))
|
||||
global, module := GlobalConfigForTests(ctx), testSystemModuleConfig(ctx, "test")
|
||||
config := android.TestConfig("out", nil, "", nil)
|
||||
ctx := android.PathContextForTesting(config)
|
||||
globalSoong := GlobalSoongConfigForTests(config)
|
||||
global := GlobalConfigForTests(ctx)
|
||||
module := testSystemModuleConfig(ctx, "test")
|
||||
|
||||
module.ProfileClassListing = android.OptionalPathForPath(android.PathForTesting("profile"))
|
||||
|
||||
rule, err := GenerateDexpreoptRule(ctx, global, module)
|
||||
rule, err := GenerateDexpreoptRule(ctx, globalSoong, global, module)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
|
|
@ -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",
|
||||
}
|
||||
`
|
||||
}
|
10
java/app.go
10
java/app.go
|
@ -142,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
|
||||
}
|
||||
|
@ -338,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()
|
||||
|
@ -922,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()
|
||||
|
@ -1064,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)
|
||||
|
||||
|
|
|
@ -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,8 +62,8 @@ type DexpreoptProperties struct {
|
|||
}
|
||||
}
|
||||
|
||||
func (d *dexpreopter) dexpreoptDisabled(ctx android.ModuleContext) bool {
|
||||
global := dexpreoptGlobalConfig(ctx)
|
||||
func (d *dexpreopter) dexpreoptDisabled(ctx android.BaseModuleContext) bool {
|
||||
global := dexpreopt.GetGlobalConfig(ctx)
|
||||
|
||||
if global.DisablePreopt {
|
||||
return true
|
||||
|
@ -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,16 +103,28 @@ 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), dexpreoptGlobalConfig(ctx))
|
||||
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
|
||||
}
|
||||
|
||||
global := dexpreoptGlobalConfig(ctx)
|
||||
globalSoong := dexpreopt.GetGlobalSoongConfig(ctx)
|
||||
global := dexpreopt.GetGlobalConfig(ctx)
|
||||
bootImage := defaultBootImageConfig(ctx)
|
||||
dexFiles := bootImage.dexPathsDeps.Paths()
|
||||
dexLocations := bootImage.dexLocationsDeps
|
||||
|
@ -156,7 +176,7 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Mo
|
|||
}
|
||||
}
|
||||
|
||||
dexpreoptConfig := dexpreopt.ModuleConfig{
|
||||
dexpreoptConfig := &dexpreopt.ModuleConfig{
|
||||
Name: ctx.ModuleName(),
|
||||
DexLocation: dexLocation,
|
||||
BuildPath: android.PathForModuleOut(ctx, "dexpreopt", ctx.ModuleName()+".jar").OutputPath,
|
||||
|
@ -191,7 +211,7 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Mo
|
|||
PresignedPrebuilt: d.isPresignedPrebuilt,
|
||||
}
|
||||
|
||||
dexpreoptRule, err := dexpreopt.GenerateDexpreoptRule(ctx, global, dexpreoptConfig)
|
||||
dexpreoptRule, err := dexpreopt.GenerateDexpreoptRule(ctx, globalSoong, global, dexpreoptConfig)
|
||||
if err != nil {
|
||||
ctx.ModuleErrorf("error generating dexpreopt rule: %s", err.Error())
|
||||
return dexJarFile
|
||||
|
|
|
@ -165,7 +165,7 @@ func dexpreoptBootJarsFactory() android.Singleton {
|
|||
}
|
||||
|
||||
func skipDexpreoptBootJars(ctx android.PathContext) bool {
|
||||
if dexpreoptGlobalConfig(ctx).DisablePreopt {
|
||||
if dexpreopt.GetGlobalConfig(ctx).DisablePreopt {
|
||||
return true
|
||||
}
|
||||
|
||||
|
@ -205,11 +205,15 @@ 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)
|
||||
|
||||
global := dexpreoptGlobalConfig(ctx)
|
||||
global := dexpreopt.GetGlobalConfig(ctx)
|
||||
|
||||
// Skip recompiling the boot image for the second sanitization phase. We'll get separate paths
|
||||
// and invalidate first-stage artifacts which are crucial to SANITIZE_LITE builds.
|
||||
|
@ -295,7 +299,8 @@ func buildBootImage(ctx android.SingletonContext, config bootImageConfig) *bootI
|
|||
func buildBootImageRuleForArch(ctx android.SingletonContext, image *bootImage,
|
||||
arch android.ArchType, profile android.Path, missingDeps []string) android.WritablePaths {
|
||||
|
||||
global := dexpreoptGlobalConfig(ctx)
|
||||
globalSoong := dexpreopt.GetCachedGlobalSoongConfig(ctx)
|
||||
global := dexpreopt.GetGlobalConfig(ctx)
|
||||
|
||||
symbolsDir := image.symbolsDir.Join(ctx, image.installSubdir, arch.String())
|
||||
symbolsFile := symbolsDir.Join(ctx, image.stem+".oat")
|
||||
|
@ -330,7 +335,7 @@ func buildBootImageRuleForArch(ctx android.SingletonContext, image *bootImage,
|
|||
|
||||
invocationPath := outputPath.ReplaceExtension(ctx, "invocation")
|
||||
|
||||
cmd.Tool(global.SoongConfig.Dex2oat).
|
||||
cmd.Tool(globalSoong.Dex2oat).
|
||||
Flag("--avoid-storing-invocation").
|
||||
FlagWithOutput("--write-invocation-to=", invocationPath).ImplicitOutput(invocationPath).
|
||||
Flag("--runtime-arg").FlagWithArg("-Xms", global.Dex2oatImageXms).
|
||||
|
@ -433,7 +438,8 @@ It is likely that the boot classpath is inconsistent.
|
|||
Rebuild with ART_BOOT_IMAGE_EXTRA_ARGS="--runtime-arg -verbose:verifier" to see verification errors.`
|
||||
|
||||
func bootImageProfileRule(ctx android.SingletonContext, image *bootImage, missingDeps []string) android.WritablePath {
|
||||
global := dexpreoptGlobalConfig(ctx)
|
||||
globalSoong := dexpreopt.GetCachedGlobalSoongConfig(ctx)
|
||||
global := dexpreopt.GetGlobalConfig(ctx)
|
||||
|
||||
if global.DisableGenerateProfile || ctx.Config().IsPdkBuild() || ctx.Config().UnbundledBuild() {
|
||||
return nil
|
||||
|
@ -464,7 +470,7 @@ func bootImageProfileRule(ctx android.SingletonContext, image *bootImage, missin
|
|||
|
||||
rule.Command().
|
||||
Text(`ANDROID_LOG_TAGS="*:e"`).
|
||||
Tool(global.SoongConfig.Profman).
|
||||
Tool(globalSoong.Profman).
|
||||
FlagWithInput("--create-profile-from=", bootImageProfile).
|
||||
FlagForEachInput("--apk=", image.dexPathsDeps.Paths()).
|
||||
FlagForEachArg("--dex-location=", image.dexLocationsDeps).
|
||||
|
@ -487,7 +493,8 @@ func bootImageProfileRule(ctx android.SingletonContext, image *bootImage, missin
|
|||
var bootImageProfileRuleKey = android.NewOnceKey("bootImageProfileRule")
|
||||
|
||||
func bootFrameworkProfileRule(ctx android.SingletonContext, image *bootImage, missingDeps []string) android.WritablePath {
|
||||
global := dexpreoptGlobalConfig(ctx)
|
||||
globalSoong := dexpreopt.GetCachedGlobalSoongConfig(ctx)
|
||||
global := dexpreopt.GetGlobalConfig(ctx)
|
||||
|
||||
if global.DisableGenerateProfile || ctx.Config().IsPdkBuild() || ctx.Config().UnbundledBuild() {
|
||||
return nil
|
||||
|
@ -513,7 +520,7 @@ func bootFrameworkProfileRule(ctx android.SingletonContext, image *bootImage, mi
|
|||
|
||||
rule.Command().
|
||||
Text(`ANDROID_LOG_TAGS="*:e"`).
|
||||
Tool(global.SoongConfig.Profman).
|
||||
Tool(globalSoong.Profman).
|
||||
Flag("--generate-boot-profile").
|
||||
FlagWithInput("--create-profile-from=", bootFrameworkProfile).
|
||||
FlagForEachInput("--apk=", image.dexPathsDeps.Paths()).
|
||||
|
@ -575,7 +582,7 @@ func dumpOatRules(ctx android.SingletonContext, image *bootImage) {
|
|||
}
|
||||
|
||||
func writeGlobalConfigForMake(ctx android.SingletonContext, path android.WritablePath) {
|
||||
data := dexpreoptGlobalConfigRaw(ctx).data
|
||||
data := dexpreopt.GetGlobalConfigRawData(ctx)
|
||||
|
||||
ctx.Build(pctx, android.BuildParams{
|
||||
Rule: android.WriteFile,
|
||||
|
|
|
@ -49,7 +49,7 @@ func TestDexpreoptBootJars(t *testing.T) {
|
|||
pathCtx := android.PathContextForTesting(config)
|
||||
dexpreoptConfig := dexpreopt.GlobalConfigForTests(pathCtx)
|
||||
dexpreoptConfig.BootJars = []string{"foo", "bar", "baz"}
|
||||
setDexpreoptTestGlobalConfig(config, dexpreoptConfig)
|
||||
dexpreopt.SetTestGlobalConfig(config, dexpreoptConfig)
|
||||
|
||||
ctx := testContext()
|
||||
|
||||
|
|
|
@ -22,57 +22,12 @@ import (
|
|||
"android/soong/dexpreopt"
|
||||
)
|
||||
|
||||
// dexpreoptGlobalConfig returns the global dexpreopt.config. It is loaded once the first time it is called for any
|
||||
// ctx.Config(), and returns the same data for all future calls with the same ctx.Config(). A value can be inserted
|
||||
// for tests using setDexpreoptTestGlobalConfig.
|
||||
func dexpreoptGlobalConfig(ctx android.PathContext) dexpreopt.GlobalConfig {
|
||||
return dexpreoptGlobalConfigRaw(ctx).global
|
||||
}
|
||||
|
||||
type globalConfigAndRaw struct {
|
||||
global dexpreopt.GlobalConfig
|
||||
data []byte
|
||||
}
|
||||
|
||||
func dexpreoptGlobalConfigRaw(ctx android.PathContext) globalConfigAndRaw {
|
||||
return ctx.Config().Once(dexpreoptGlobalConfigKey, func() interface{} {
|
||||
if data, err := ctx.Config().DexpreoptGlobalConfig(ctx); err != nil {
|
||||
panic(err)
|
||||
} else if data != nil {
|
||||
soongConfig := dexpreopt.CreateGlobalSoongConfig(ctx)
|
||||
globalConfig, err := dexpreopt.LoadGlobalConfig(ctx, data, soongConfig)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return globalConfigAndRaw{globalConfig, data}
|
||||
}
|
||||
|
||||
// No global config filename set, see if there is a test config set
|
||||
return ctx.Config().Once(dexpreoptTestGlobalConfigKey, func() interface{} {
|
||||
// Nope, return a config with preopting disabled
|
||||
return globalConfigAndRaw{dexpreopt.GlobalConfig{
|
||||
DisablePreopt: true,
|
||||
DisableGenerateProfile: true,
|
||||
}, nil}
|
||||
})
|
||||
}).(globalConfigAndRaw)
|
||||
}
|
||||
|
||||
// setDexpreoptTestGlobalConfig sets a GlobalConfig that future calls to dexpreoptGlobalConfig will return. It must
|
||||
// be called before the first call to dexpreoptGlobalConfig for the config.
|
||||
func setDexpreoptTestGlobalConfig(config android.Config, globalConfig dexpreopt.GlobalConfig) {
|
||||
config.Once(dexpreoptTestGlobalConfigKey, func() interface{} { return globalConfigAndRaw{globalConfig, nil} })
|
||||
}
|
||||
|
||||
var dexpreoptGlobalConfigKey = android.NewOnceKey("DexpreoptGlobalConfig")
|
||||
var dexpreoptTestGlobalConfigKey = android.NewOnceKey("TestDexpreoptGlobalConfig")
|
||||
|
||||
// systemServerClasspath returns the on-device locations of the modules in the system server classpath. It is computed
|
||||
// once the first time it is called for any ctx.Config(), and returns the same slice for all future calls with the same
|
||||
// ctx.Config().
|
||||
func systemServerClasspath(ctx android.MakeVarsContext) []string {
|
||||
return ctx.Config().OnceStringSlice(systemServerClasspathKey, func() []string {
|
||||
global := dexpreoptGlobalConfig(ctx)
|
||||
global := dexpreopt.GetGlobalConfig(ctx)
|
||||
var systemServerClasspathLocations []string
|
||||
for _, m := range *DexpreoptedSystemServerJars(ctx.Config()) {
|
||||
systemServerClasspathLocations = append(systemServerClasspathLocations,
|
||||
|
@ -121,7 +76,7 @@ var (
|
|||
func genBootImageConfigs(ctx android.PathContext) map[string]*bootImageConfig {
|
||||
return ctx.Config().Once(bootImageConfigKey, func() interface{} {
|
||||
|
||||
global := dexpreoptGlobalConfig(ctx)
|
||||
global := dexpreopt.GetGlobalConfig(ctx)
|
||||
targets := dexpreoptTargets(ctx)
|
||||
deviceDir := android.PathForOutput(ctx, ctx.Config().DeviceName())
|
||||
|
||||
|
@ -227,7 +182,7 @@ func defaultBootImageConfig(ctx android.PathContext) bootImageConfig {
|
|||
|
||||
func defaultBootclasspath(ctx android.PathContext) []string {
|
||||
return ctx.Config().OnceStringSlice(defaultBootclasspathKey, func() []string {
|
||||
global := dexpreoptGlobalConfig(ctx)
|
||||
global := dexpreopt.GetGlobalConfig(ctx)
|
||||
image := defaultBootImageConfig(ctx)
|
||||
|
||||
updatableBootclasspath := make([]string, len(global.UpdatableBootJars))
|
||||
|
|
16
java/java.go
16
java/java.go
|
@ -76,6 +76,10 @@ func RegisterJavaBuildComponents(ctx android.RegistrationContext) {
|
|||
ctx.RegisterModuleType("java_host_for_device", HostForDeviceFactory)
|
||||
ctx.RegisterModuleType("dex_import", DexImportFactory)
|
||||
|
||||
ctx.FinalDepsMutators(func(ctx android.RegisterMutatorsContext) {
|
||||
ctx.BottomUp("dexpreopt_tool_deps", dexpreoptToolDepsMutator).Parallel()
|
||||
})
|
||||
|
||||
ctx.RegisterSingletonType("logtags", LogtagsSingleton)
|
||||
ctx.RegisterSingletonType("kythe_java_extract", kytheExtractJavaFactory)
|
||||
}
|
||||
|
@ -105,7 +109,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()
|
||||
|
@ -1781,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)
|
||||
//
|
||||
|
@ -1818,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)
|
||||
|
@ -2575,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")
|
||||
|
|
|
@ -57,7 +57,15 @@ func TestMain(m *testing.M) {
|
|||
}
|
||||
|
||||
func testConfig(env map[string]string, bp string, fs map[string][]byte) android.Config {
|
||||
return TestConfig(buildDir, env, bp, fs)
|
||||
bp += dexpreopt.BpToolModulesForTest()
|
||||
|
||||
config := TestConfig(buildDir, env, bp, fs)
|
||||
|
||||
// Set up the global Once cache used for dexpreopt.GlobalSoongConfig, so that
|
||||
// it doesn't create a real one, which would fail.
|
||||
_ = dexpreopt.GlobalSoongConfigForTests(config)
|
||||
|
||||
return config
|
||||
}
|
||||
|
||||
func testContext() *android.TestContext {
|
||||
|
@ -86,6 +94,8 @@ func testContext() *android.TestContext {
|
|||
cc.RegisterRequiredBuildComponentsForTest(ctx)
|
||||
ctx.RegisterModuleType("ndk_prebuilt_shared_stl", cc.NdkPrebuiltSharedStlFactory)
|
||||
|
||||
dexpreopt.RegisterToolModulesForTest(ctx)
|
||||
|
||||
return ctx
|
||||
}
|
||||
|
||||
|
@ -93,7 +103,7 @@ func run(t *testing.T, ctx *android.TestContext, config android.Config) {
|
|||
t.Helper()
|
||||
|
||||
pathCtx := android.PathContextForTesting(config)
|
||||
setDexpreoptTestGlobalConfig(config, dexpreopt.GlobalConfigForTests(pathCtx))
|
||||
dexpreopt.SetTestGlobalConfig(config, dexpreopt.GlobalConfigForTests(pathCtx))
|
||||
|
||||
ctx.Register(config)
|
||||
_, errs := ctx.ParseBlueprintsFiles("Android.bp")
|
||||
|
@ -112,7 +122,7 @@ func testJavaErrorWithConfig(t *testing.T, pattern string, config android.Config
|
|||
ctx := testContext()
|
||||
|
||||
pathCtx := android.PathContextForTesting(config)
|
||||
setDexpreoptTestGlobalConfig(config, dexpreopt.GlobalConfigForTests(pathCtx))
|
||||
dexpreopt.SetTestGlobalConfig(config, dexpreopt.GlobalConfigForTests(pathCtx))
|
||||
|
||||
ctx.Register(config)
|
||||
_, errs := ctx.ParseBlueprintsFiles("Android.bp")
|
||||
|
|
Loading…
Reference in New Issue