Merge "Write module dexpreopt.config for Make."
This commit is contained in:
commit
a4fce3b488
7 changed files with 110 additions and 5 deletions
|
@ -534,3 +534,26 @@ func fromJsonClassLoaderContextRec(ctx android.PathContext, jClcs map[string]*js
|
|||
}
|
||||
return clcs
|
||||
}
|
||||
|
||||
// Convert Soong CLC map to JSON representation for Make.
|
||||
func toJsonClassLoaderContext(clcMap ClassLoaderContextMap) jsonClassLoaderContextMap {
|
||||
jClcMap := make(jsonClassLoaderContextMap)
|
||||
for sdkVer, clcs := range clcMap {
|
||||
sdkVerStr := fmt.Sprintf("%d", sdkVer)
|
||||
jClcMap[sdkVerStr] = toJsonClassLoaderContextRec(clcs)
|
||||
}
|
||||
return jClcMap
|
||||
}
|
||||
|
||||
// Recursive helper for toJsonClassLoaderContext.
|
||||
func toJsonClassLoaderContextRec(clcs []*ClassLoaderContext) map[string]*jsonClassLoaderContext {
|
||||
jClcs := make(map[string]*jsonClassLoaderContext, len(clcs))
|
||||
for _, clc := range clcs {
|
||||
jClcs[clc.Name] = &jsonClassLoaderContext{
|
||||
Host: clc.Host.String(),
|
||||
Device: clc.Device,
|
||||
Subcontexts: toJsonClassLoaderContextRec(clc.Subcontexts),
|
||||
}
|
||||
}
|
||||
return jClcs
|
||||
}
|
||||
|
|
|
@ -114,6 +114,7 @@ type ModuleConfig struct {
|
|||
ProfileBootListing android.OptionalPath
|
||||
|
||||
EnforceUsesLibraries bool
|
||||
ProvidesUsesLibrary string // the name of the <uses-library> (usually the same as its module)
|
||||
ClassLoaderContexts ClassLoaderContextMap
|
||||
|
||||
Archs []android.ArchType
|
||||
|
@ -290,6 +291,42 @@ func ParseModuleConfig(ctx android.PathContext, data []byte) (*ModuleConfig, err
|
|||
return config.ModuleConfig, nil
|
||||
}
|
||||
|
||||
// WriteSlimModuleConfigForMake serializes a subset of ModuleConfig into a per-module
|
||||
// dexpreopt.config JSON file. It is a way to pass dexpreopt information about Soong modules to
|
||||
// Make, which is needed when a Make module has a <uses-library> dependency on a Soong module.
|
||||
func WriteSlimModuleConfigForMake(ctx android.ModuleContext, config *ModuleConfig, path android.WritablePath) {
|
||||
if path == nil {
|
||||
return
|
||||
}
|
||||
|
||||
// JSON representation of the slim module dexpreopt.config.
|
||||
type slimModuleJSONConfig struct {
|
||||
Name string
|
||||
DexLocation string
|
||||
BuildPath string
|
||||
EnforceUsesLibraries bool
|
||||
ProvidesUsesLibrary string
|
||||
ClassLoaderContexts jsonClassLoaderContextMap
|
||||
}
|
||||
|
||||
jsonConfig := &slimModuleJSONConfig{
|
||||
Name: config.Name,
|
||||
DexLocation: config.DexLocation,
|
||||
BuildPath: config.BuildPath.String(),
|
||||
EnforceUsesLibraries: config.EnforceUsesLibraries,
|
||||
ProvidesUsesLibrary: config.ProvidesUsesLibrary,
|
||||
ClassLoaderContexts: toJsonClassLoaderContext(config.ClassLoaderContexts),
|
||||
}
|
||||
|
||||
data, err := json.MarshalIndent(jsonConfig, "", " ")
|
||||
if err != nil {
|
||||
ctx.ModuleErrorf("failed to JSON marshal module dexpreopt.config: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
android.WriteFileRule(ctx, path, string(data))
|
||||
}
|
||||
|
||||
// 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.
|
||||
|
|
|
@ -125,6 +125,10 @@ func (library *Library) AndroidMkEntries() []android.AndroidMkEntries {
|
|||
entries.SetString("LOCAL_MODULE_STEM", library.Stem())
|
||||
|
||||
entries.SetOptionalPaths("LOCAL_SOONG_LINT_REPORTS", library.linter.reports)
|
||||
|
||||
if library.dexpreopter.configPath != nil {
|
||||
entries.SetPath("LOCAL_SOONG_DEXPREOPT_CONFIG", library.dexpreopter.configPath)
|
||||
}
|
||||
},
|
||||
},
|
||||
})
|
||||
|
|
|
@ -455,6 +455,7 @@ func (a *AndroidApp) installPath(ctx android.ModuleContext) android.InstallPath
|
|||
|
||||
func (a *AndroidApp) dexBuildActions(ctx android.ModuleContext) android.Path {
|
||||
a.dexpreopter.installPath = a.installPath(ctx)
|
||||
a.dexpreopter.isApp = true
|
||||
if a.dexProperties.Uncompress_dex == nil {
|
||||
// If the value was not force-set by the user, use reasonable default based on the module.
|
||||
a.dexProperties.Uncompress_dex = proptools.BoolPtr(a.shouldUncompressDex(ctx))
|
||||
|
|
|
@ -255,6 +255,7 @@ func (a *AndroidAppImport) generateAndroidBuildActions(ctx android.ModuleContext
|
|||
installDir = android.PathForModuleInstall(ctx, "app", a.BaseModuleName())
|
||||
}
|
||||
|
||||
a.dexpreopter.isApp = true
|
||||
a.dexpreopter.installPath = installDir.Join(ctx, a.BaseModuleName()+".apk")
|
||||
a.dexpreopter.isPresignedPrebuilt = Bool(a.properties.Presigned)
|
||||
a.dexpreopter.uncompressedDex = a.shouldUncompressDex(ctx)
|
||||
|
|
|
@ -30,6 +30,7 @@ type dexpreopter struct {
|
|||
installPath android.InstallPath
|
||||
uncompressedDex bool
|
||||
isSDKLibrary bool
|
||||
isApp bool
|
||||
isTest bool
|
||||
isPresignedPrebuilt bool
|
||||
|
||||
|
@ -38,6 +39,11 @@ type dexpreopter struct {
|
|||
classLoaderContexts dexpreopt.ClassLoaderContextMap
|
||||
|
||||
builtInstalled string
|
||||
|
||||
// A path to a dexpreopt.config file generated by Soong for libraries that may be used as a
|
||||
// <uses-library> by Make modules. The path is passed to Make via LOCAL_SOONG_DEXPREOPT_CONFIG
|
||||
// variable. If the path is nil, no config is generated (which is the case for apps and tests).
|
||||
configPath android.WritablePath
|
||||
}
|
||||
|
||||
type DexpreoptProperties struct {
|
||||
|
@ -117,7 +123,40 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Mo
|
|||
// 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() == "." {
|
||||
if d.installPath.Base() == "." {
|
||||
return
|
||||
}
|
||||
|
||||
dexLocation := android.InstallPathToOnDevicePath(ctx, d.installPath)
|
||||
|
||||
buildPath := android.PathForModuleOut(ctx, "dexpreopt", ctx.ModuleName()+".jar").OutputPath
|
||||
|
||||
providesUsesLib := ctx.ModuleName()
|
||||
if ulib, ok := ctx.Module().(ProvidesUsesLib); ok {
|
||||
name := ulib.ProvidesUsesLib()
|
||||
if name != nil {
|
||||
providesUsesLib = *name
|
||||
}
|
||||
}
|
||||
|
||||
if !d.isApp && !d.isTest {
|
||||
// Slim dexpreopt config is serialized to dexpreopt.config files and used by
|
||||
// dex_preopt_config_merger.py to get information about <uses-library> dependencies.
|
||||
// Note that it might be needed even if dexpreopt is disabled for this module.
|
||||
slimDexpreoptConfig := &dexpreopt.ModuleConfig{
|
||||
Name: ctx.ModuleName(),
|
||||
DexLocation: dexLocation,
|
||||
BuildPath: buildPath,
|
||||
EnforceUsesLibraries: d.enforceUsesLibs,
|
||||
ProvidesUsesLibrary: providesUsesLib,
|
||||
ClassLoaderContexts: d.classLoaderContexts,
|
||||
// The rest of the fields are not needed.
|
||||
}
|
||||
d.configPath = android.PathForModuleOut(ctx, "dexpreopt", "dexpreopt.config")
|
||||
dexpreopt.WriteSlimModuleConfigForMake(ctx, slimDexpreoptConfig, d.configPath)
|
||||
}
|
||||
|
||||
if d.dexpreoptDisabled(ctx) {
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -157,8 +196,6 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Mo
|
|||
// The image locations for all Android variants are identical.
|
||||
imageLocations := bootImage.getAnyAndroidVariant().imageLocations()
|
||||
|
||||
dexLocation := android.InstallPathToOnDevicePath(ctx, d.installPath)
|
||||
|
||||
var profileClassListing android.OptionalPath
|
||||
var profileBootListing android.OptionalPath
|
||||
profileIsTextListing := false
|
||||
|
@ -177,10 +214,11 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Mo
|
|||
}
|
||||
}
|
||||
|
||||
// Full dexpreopt config, used to create dexpreopt build rules.
|
||||
dexpreoptConfig := &dexpreopt.ModuleConfig{
|
||||
Name: ctx.ModuleName(),
|
||||
DexLocation: dexLocation,
|
||||
BuildPath: android.PathForModuleOut(ctx, "dexpreopt", ctx.ModuleName()+".jar").OutputPath,
|
||||
BuildPath: buildPath,
|
||||
DexPath: dexJarFile,
|
||||
ManifestPath: d.manifestFile,
|
||||
UncompressedDex: d.uncompressedDex,
|
||||
|
@ -192,6 +230,7 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Mo
|
|||
ProfileBootListing: profileBootListing,
|
||||
|
||||
EnforceUsesLibraries: d.enforceUsesLibs,
|
||||
ProvidesUsesLibrary: providesUsesLib,
|
||||
ClassLoaderContexts: d.classLoaderContexts,
|
||||
|
||||
Archs: archs,
|
||||
|
|
|
@ -148,7 +148,7 @@ func TestDexpreoptEnabled(t *testing.T) {
|
|||
t.Run(test.name, func(t *testing.T) {
|
||||
ctx, _ := testJava(t, test.bp)
|
||||
|
||||
dexpreopt := ctx.ModuleForTests("foo", "android_common").MaybeDescription("dexpreopt")
|
||||
dexpreopt := ctx.ModuleForTests("foo", "android_common").MaybeRule("dexpreopt")
|
||||
enabled := dexpreopt.Rule != nil
|
||||
|
||||
if enabled != test.enabled {
|
||||
|
|
Loading…
Reference in a new issue