Move generation of the dexpreopt tool paths into Soong.
The dexpreopt global config is now split into the part that is generated from make (in build/make/core/dex_preopt_config.mk) and the part that is generated from Soong. Since the goal is to generate the dex2oat path from Soong dependencies, the old GlobalConfig.Tools struct is simply repurposed for the Soong generated config, although the intention is to allow more settings to migrate from make to Soong, and hence from GlobalConfig to GlobalSoongConfig. Since the new dexpreopt_soong.config is written from a Soong-created ninja rule, it doesn't need to be rewritten to out/soong/<device>/ like the old make-created config file. Test: m Test: env USE_DEX2OAT_DEBUG=false m (check that out/soong/dexpreopt_soong.config points to dex2oat instead of dex2oatd) Bug: 145934348 Change-Id: Ifd45c4a08e2ec55b86f4a93f0d85bd39cf2cf189
This commit is contained in:
parent
99d522b5df
commit
c52aaf11d0
5 changed files with 165 additions and 56 deletions
|
@ -22,7 +22,9 @@ import (
|
|||
"android/soong/android"
|
||||
)
|
||||
|
||||
// GlobalConfig stores the configuration for dex preopting set by the product
|
||||
// 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.
|
||||
type GlobalConfig struct {
|
||||
DisablePreopt bool // disable preopt for all modules
|
||||
DisablePreoptModules []string // modules with preopt disabled by product-specific config
|
||||
|
@ -82,19 +84,19 @@ type GlobalConfig struct {
|
|||
Dex2oatImageXmx string // max heap size for dex2oat for the boot image
|
||||
Dex2oatImageXms string // initial heap size for dex2oat for the boot image
|
||||
|
||||
Tools Tools // paths to tools possibly used by the generated commands
|
||||
SoongConfig GlobalSoongConfig // settings read from dexpreopt_soong.config
|
||||
}
|
||||
|
||||
// Tools contains paths to tools possibly used by the generated commands. If you add a new tool here you MUST add it
|
||||
// to the order-only dependency list in DEXPREOPT_GEN_DEPS.
|
||||
type Tools struct {
|
||||
// GlobalSoongConfig contains the global config that is generated from Soong,
|
||||
// stored in dexpreopt_soong.config.
|
||||
type GlobalSoongConfig struct {
|
||||
// Paths to tools possibly used by the generated commands.
|
||||
Profman android.Path
|
||||
Dex2oat android.Path
|
||||
Aapt android.Path
|
||||
SoongZip android.Path
|
||||
Zip2zip android.Path
|
||||
ManifestCheck android.Path
|
||||
|
||||
ConstructContext android.Path
|
||||
}
|
||||
|
||||
|
@ -133,6 +135,17 @@ type ModuleConfig struct {
|
|||
PresignedPrebuilt bool
|
||||
}
|
||||
|
||||
type globalSoongConfigSingleton struct{}
|
||||
|
||||
var pctx = android.NewPackageContext("android/soong/dexpreopt")
|
||||
|
||||
func init() {
|
||||
pctx.Import("android/soong/android")
|
||||
android.RegisterSingletonType("dexpreopt-soong-config", func() android.Singleton {
|
||||
return &globalSoongConfigSingleton{}
|
||||
})
|
||||
}
|
||||
|
||||
func constructPath(ctx android.PathContext, path string) android.Path {
|
||||
buildDirPrefix := ctx.Config().BuildDir() + "/"
|
||||
if path == "" {
|
||||
|
@ -167,9 +180,12 @@ 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. It 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, path string) (GlobalConfig, []byte, error) {
|
||||
// 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, path string, soongConfig GlobalSoongConfig) (GlobalConfig, []byte, error) {
|
||||
type GlobalJSONConfig struct {
|
||||
GlobalConfig
|
||||
|
||||
|
@ -177,17 +193,6 @@ func LoadGlobalConfig(ctx android.PathContext, path string) (GlobalConfig, []byt
|
|||
// used to construct the real value manually below.
|
||||
DirtyImageObjects string
|
||||
BootImageProfiles []string
|
||||
|
||||
Tools struct {
|
||||
Profman string
|
||||
Dex2oat string
|
||||
Aapt string
|
||||
SoongZip string
|
||||
Zip2zip string
|
||||
ManifestCheck string
|
||||
|
||||
ConstructContext string
|
||||
}
|
||||
}
|
||||
|
||||
config := GlobalJSONConfig{}
|
||||
|
@ -200,13 +205,9 @@ func LoadGlobalConfig(ctx android.PathContext, path string) (GlobalConfig, []byt
|
|||
config.GlobalConfig.DirtyImageObjects = android.OptionalPathForPath(constructPath(ctx, config.DirtyImageObjects))
|
||||
config.GlobalConfig.BootImageProfiles = constructPaths(ctx, config.BootImageProfiles)
|
||||
|
||||
config.GlobalConfig.Tools.Profman = constructPath(ctx, config.Tools.Profman)
|
||||
config.GlobalConfig.Tools.Dex2oat = constructPath(ctx, config.Tools.Dex2oat)
|
||||
config.GlobalConfig.Tools.Aapt = constructPath(ctx, config.Tools.Aapt)
|
||||
config.GlobalConfig.Tools.SoongZip = constructPath(ctx, config.Tools.SoongZip)
|
||||
config.GlobalConfig.Tools.Zip2zip = constructPath(ctx, config.Tools.Zip2zip)
|
||||
config.GlobalConfig.Tools.ManifestCheck = constructPath(ctx, config.Tools.ManifestCheck)
|
||||
config.GlobalConfig.Tools.ConstructContext = constructPath(ctx, config.Tools.ConstructContext)
|
||||
// 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, data, nil
|
||||
}
|
||||
|
@ -253,6 +254,104 @@ func LoadModuleConfig(ctx android.PathContext, path string) (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.
|
||||
// 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),
|
||||
Aapt: ctx.Config().HostToolPath(ctx, "aapt"),
|
||||
SoongZip: ctx.Config().HostToolPath(ctx, "soong_zip"),
|
||||
Zip2zip: ctx.Config().HostToolPath(ctx, "zip2zip"),
|
||||
ManifestCheck: ctx.Config().HostToolPath(ctx, "manifest_check"),
|
||||
ConstructContext: android.PathForSource(ctx, "build/make/core/construct_context.sh"),
|
||||
}
|
||||
}
|
||||
|
||||
type globalJsonSoongConfig struct {
|
||||
Profman string
|
||||
Dex2oat string
|
||||
Aapt string
|
||||
SoongZip string
|
||||
Zip2zip string
|
||||
ManifestCheck string
|
||||
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, path string) (GlobalSoongConfig, error) {
|
||||
var jc globalJsonSoongConfig
|
||||
|
||||
_, err := loadConfig(ctx, path, &jc)
|
||||
if err != nil {
|
||||
return GlobalSoongConfig{}, err
|
||||
}
|
||||
|
||||
config := GlobalSoongConfig{
|
||||
Profman: constructPath(ctx, jc.Profman),
|
||||
Dex2oat: constructPath(ctx, jc.Dex2oat),
|
||||
Aapt: constructPath(ctx, jc.Aapt),
|
||||
SoongZip: constructPath(ctx, jc.SoongZip),
|
||||
Zip2zip: constructPath(ctx, jc.Zip2zip),
|
||||
ManifestCheck: constructPath(ctx, jc.ManifestCheck),
|
||||
ConstructContext: constructPath(ctx, jc.ConstructContext),
|
||||
}
|
||||
|
||||
return config, nil
|
||||
}
|
||||
|
||||
func (s *globalSoongConfigSingleton) GenerateBuildActions(ctx android.SingletonContext) {
|
||||
config := CreateGlobalSoongConfig(ctx)
|
||||
jc := globalJsonSoongConfig{
|
||||
Profman: config.Profman.String(),
|
||||
Dex2oat: config.Dex2oat.String(),
|
||||
Aapt: config.Aapt.String(),
|
||||
SoongZip: config.SoongZip.String(),
|
||||
Zip2zip: config.Zip2zip.String(),
|
||||
ManifestCheck: config.ManifestCheck.String(),
|
||||
ConstructContext: config.ConstructContext.String(),
|
||||
}
|
||||
|
||||
data, err := json.Marshal(jc)
|
||||
if err != nil {
|
||||
ctx.Errorf("failed to JSON marshal GlobalSoongConfig: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Build(pctx, android.BuildParams{
|
||||
Rule: android.WriteFile,
|
||||
Output: android.PathForOutput(ctx, "dexpreopt_soong.config"),
|
||||
Args: map[string]string{
|
||||
"content": string(data),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func (s *globalSoongConfigSingleton) MakeVars(ctx android.MakeVarsContext) {
|
||||
config := CreateGlobalSoongConfig(ctx)
|
||||
|
||||
ctx.Strict("DEX2OAT", config.Dex2oat.String())
|
||||
ctx.Strict("DEXPREOPT_GEN_DEPS", strings.Join([]string{
|
||||
config.Profman.String(),
|
||||
config.Dex2oat.String(),
|
||||
config.Aapt.String(),
|
||||
config.SoongZip.String(),
|
||||
config.Zip2zip.String(),
|
||||
config.ManifestCheck.String(),
|
||||
config.ConstructContext.String(),
|
||||
}, " "))
|
||||
}
|
||||
|
||||
func loadConfig(ctx android.PathContext, path string, config interface{}) ([]byte, error) {
|
||||
r, err := ctx.Fs().Open(path)
|
||||
if err != nil {
|
||||
|
@ -312,7 +411,7 @@ func GlobalConfigForTests(ctx android.PathContext) GlobalConfig {
|
|||
BootFlags: "",
|
||||
Dex2oatImageXmx: "",
|
||||
Dex2oatImageXms: "",
|
||||
Tools: Tools{
|
||||
SoongConfig: GlobalSoongConfig{
|
||||
Profman: android.PathForTesting("profman"),
|
||||
Dex2oat: android.PathForTesting("dex2oat"),
|
||||
Aapt: android.PathForTesting("aapt"),
|
||||
|
|
|
@ -131,7 +131,7 @@ func profileCommand(ctx android.PathContext, global GlobalConfig, module ModuleC
|
|||
|
||||
cmd := rule.Command().
|
||||
Text(`ANDROID_LOG_TAGS="*:e"`).
|
||||
Tool(global.Tools.Profman)
|
||||
Tool(global.SoongConfig.Profman)
|
||||
|
||||
if module.ProfileIsTextListing {
|
||||
// The profile is a test listing of classes (used for framework jars).
|
||||
|
@ -170,7 +170,7 @@ func bootProfileCommand(ctx android.PathContext, global GlobalConfig, module Mod
|
|||
|
||||
cmd := rule.Command().
|
||||
Text(`ANDROID_LOG_TAGS="*:e"`).
|
||||
Tool(global.Tools.Profman)
|
||||
Tool(global.SoongConfig.Profman)
|
||||
|
||||
// The profile is a test listing of methods.
|
||||
// We need to generate the actual binary profile.
|
||||
|
@ -299,14 +299,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.Tools.ManifestCheck).
|
||||
Tool(global.SoongConfig.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.Tools.Aapt).
|
||||
Tool(global.SoongConfig.Aapt).
|
||||
Flag("dump badging").
|
||||
Input(module.DexPath).
|
||||
Text(`| grep "targetSdkVersion" | sed -n "s/targetSdkVersion:'\(.*\)'/\1/p"`).
|
||||
|
@ -327,7 +327,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.Tools.ConstructContext).Input(module.DexPath)
|
||||
rule.Command().Text("source").Tool(global.SoongConfig.ConstructContext).Input(module.DexPath)
|
||||
}
|
||||
|
||||
// Devices that do not have a product partition use a symlink from /product to /system/product.
|
||||
|
@ -340,7 +340,7 @@ func dexpreoptCommand(ctx android.PathContext, global GlobalConfig, module Modul
|
|||
|
||||
cmd := rule.Command().
|
||||
Text(`ANDROID_LOG_TAGS="*:e"`).
|
||||
Tool(global.Tools.Dex2oat).
|
||||
Tool(global.SoongConfig.Dex2oat).
|
||||
Flag("--avoid-storing-invocation").
|
||||
FlagWithOutput("--write-invocation-to=", invocationPath).ImplicitOutput(invocationPath).
|
||||
Flag("--runtime-arg").FlagWithArg("-Xms", global.Dex2oatXms).
|
||||
|
@ -409,7 +409,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.Tools.SoongZip).
|
||||
rule.Command().Tool(global.SoongConfig.SoongZip).
|
||||
FlagWithArg("-L", "9").
|
||||
FlagWithOutput("-o", dmPath).
|
||||
Flag("-j").
|
||||
|
|
|
@ -31,6 +31,7 @@ import (
|
|||
|
||||
var (
|
||||
dexpreoptScriptPath = flag.String("dexpreopt_script", "", "path to output dexpreopt script")
|
||||
globalSoongConfigPath = flag.String("global_soong", "", "path to global configuration file for settings originating from Soong")
|
||||
globalConfigPath = flag.String("global", "", "path to global configuration file")
|
||||
moduleConfigPath = flag.String("module", "", "path to module configuration file")
|
||||
outDir = flag.String("out_dir", "", "path to output directory")
|
||||
|
@ -63,17 +64,27 @@ func main() {
|
|||
usage("path to output dexpreopt script is required")
|
||||
}
|
||||
|
||||
if *globalSoongConfigPath == "" {
|
||||
usage("--global_soong configuration file is required")
|
||||
}
|
||||
|
||||
if *globalConfigPath == "" {
|
||||
usage("path to global configuration file is required")
|
||||
usage("--global configuration file is required")
|
||||
}
|
||||
|
||||
if *moduleConfigPath == "" {
|
||||
usage("path to module configuration file is required")
|
||||
usage("--module configuration file is required")
|
||||
}
|
||||
|
||||
ctx := &pathContext{android.TestConfig(*outDir, nil, "", nil)}
|
||||
|
||||
globalConfig, _, err := dexpreopt.LoadGlobalConfig(ctx, *globalConfigPath)
|
||||
globalSoongConfig, err := dexpreopt.LoadGlobalSoongConfig(ctx, *globalSoongConfigPath)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "error loading global config %q: %s\n", *globalSoongConfigPath, err)
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
globalConfig, _, err := dexpreopt.LoadGlobalConfig(ctx, *globalConfigPath, globalSoongConfig)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "error loading global config %q: %s\n", *globalConfigPath, err)
|
||||
os.Exit(2)
|
||||
|
@ -121,7 +132,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.Tools.SoongZip).
|
||||
dexpreoptRule.Command().Tool(global.SoongConfig.SoongZip).
|
||||
FlagWithArg("-o ", "$2").
|
||||
FlagWithArg("-C ", installDir.String()).
|
||||
FlagWithArg("-D ", installDir.String())
|
||||
|
|
|
@ -335,7 +335,7 @@ func buildBootImageRuleForArch(ctx android.SingletonContext, image *bootImage,
|
|||
|
||||
invocationPath := outputPath.ReplaceExtension(ctx, "invocation")
|
||||
|
||||
cmd.Tool(global.Tools.Dex2oat).
|
||||
cmd.Tool(global.SoongConfig.Dex2oat).
|
||||
Flag("--avoid-storing-invocation").
|
||||
FlagWithOutput("--write-invocation-to=", invocationPath).ImplicitOutput(invocationPath).
|
||||
Flag("--runtime-arg").FlagWithArg("-Xms", global.Dex2oatImageXms).
|
||||
|
@ -444,7 +444,6 @@ func bootImageProfileRule(ctx android.SingletonContext, image *bootImage, missin
|
|||
return nil
|
||||
}
|
||||
profile := ctx.Config().Once(bootImageProfileRuleKey, func() interface{} {
|
||||
tools := global.Tools
|
||||
defaultProfile := "frameworks/base/config/boot-image-profile.txt"
|
||||
|
||||
rule := android.NewRuleBuilder()
|
||||
|
@ -470,7 +469,7 @@ func bootImageProfileRule(ctx android.SingletonContext, image *bootImage, missin
|
|||
|
||||
rule.Command().
|
||||
Text(`ANDROID_LOG_TAGS="*:e"`).
|
||||
Tool(tools.Profman).
|
||||
Tool(global.SoongConfig.Profman).
|
||||
FlagWithInput("--create-profile-from=", bootImageProfile).
|
||||
FlagForEachInput("--apk=", image.dexPathsDeps.Paths()).
|
||||
FlagForEachArg("--dex-location=", image.dexLocationsDeps).
|
||||
|
@ -499,8 +498,6 @@ func bootFrameworkProfileRule(ctx android.SingletonContext, image *bootImage, mi
|
|||
return nil
|
||||
}
|
||||
return ctx.Config().Once(bootFrameworkProfileRuleKey, func() interface{} {
|
||||
tools := global.Tools
|
||||
|
||||
rule := android.NewRuleBuilder()
|
||||
rule.MissingDeps(missingDeps)
|
||||
|
||||
|
@ -521,7 +518,7 @@ func bootFrameworkProfileRule(ctx android.SingletonContext, image *bootImage, mi
|
|||
|
||||
rule.Command().
|
||||
Text(`ANDROID_LOG_TAGS="*:e"`).
|
||||
Tool(tools.Profman).
|
||||
Tool(global.SoongConfig.Profman).
|
||||
Flag("--generate-boot-profile").
|
||||
FlagWithInput("--create-profile-from=", bootFrameworkProfile).
|
||||
FlagForEachInput("--apk=", image.dexPathsDeps.Paths()).
|
||||
|
@ -598,6 +595,7 @@ func writeGlobalConfigForMake(ctx android.SingletonContext, path android.Writabl
|
|||
func (d *dexpreoptBootJars) MakeVars(ctx android.MakeVarsContext) {
|
||||
if d.dexpreoptConfigForMake != nil {
|
||||
ctx.Strict("DEX_PREOPT_CONFIG_FOR_MAKE", d.dexpreoptConfigForMake.String())
|
||||
ctx.Strict("DEX_PREOPT_SOONG_CONFIG_FOR_MAKE", android.PathForOutput(ctx, "dexpreopt_soong.config").String())
|
||||
}
|
||||
|
||||
image := d.defaultBootImage
|
||||
|
|
|
@ -37,8 +37,9 @@ type globalConfigAndRaw struct {
|
|||
func dexpreoptGlobalConfigRaw(ctx android.PathContext) globalConfigAndRaw {
|
||||
return ctx.Config().Once(dexpreoptGlobalConfigKey, func() interface{} {
|
||||
if f := ctx.Config().DexpreoptGlobalConfig(); f != "" {
|
||||
soongConfig := dexpreopt.CreateGlobalSoongConfig(ctx)
|
||||
ctx.AddNinjaFileDeps(f)
|
||||
globalConfig, data, err := dexpreopt.LoadGlobalConfig(ctx, f)
|
||||
globalConfig, data, err := dexpreopt.LoadGlobalConfig(ctx, f, soongConfig)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue