Merge "Write module dexpreopt.config for Make."
This commit is contained in:
@@ -534,3 +534,26 @@ func fromJsonClassLoaderContextRec(ctx android.PathContext, jClcs map[string]*js
|
|||||||
}
|
}
|
||||||
return clcs
|
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
|
ProfileBootListing android.OptionalPath
|
||||||
|
|
||||||
EnforceUsesLibraries bool
|
EnforceUsesLibraries bool
|
||||||
|
ProvidesUsesLibrary string // the name of the <uses-library> (usually the same as its module)
|
||||||
ClassLoaderContexts ClassLoaderContextMap
|
ClassLoaderContexts ClassLoaderContextMap
|
||||||
|
|
||||||
Archs []android.ArchType
|
Archs []android.ArchType
|
||||||
@@ -290,6 +291,42 @@ func ParseModuleConfig(ctx android.PathContext, data []byte) (*ModuleConfig, err
|
|||||||
return config.ModuleConfig, nil
|
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
|
// 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
|
// tool. It should be a binary module with public visibility that is compiled
|
||||||
// and installed for host.
|
// and installed for host.
|
||||||
|
@@ -125,6 +125,10 @@ func (library *Library) AndroidMkEntries() []android.AndroidMkEntries {
|
|||||||
entries.SetString("LOCAL_MODULE_STEM", library.Stem())
|
entries.SetString("LOCAL_MODULE_STEM", library.Stem())
|
||||||
|
|
||||||
entries.SetOptionalPaths("LOCAL_SOONG_LINT_REPORTS", library.linter.reports)
|
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 {
|
func (a *AndroidApp) dexBuildActions(ctx android.ModuleContext) android.Path {
|
||||||
a.dexpreopter.installPath = a.installPath(ctx)
|
a.dexpreopter.installPath = a.installPath(ctx)
|
||||||
|
a.dexpreopter.isApp = true
|
||||||
if a.dexProperties.Uncompress_dex == nil {
|
if a.dexProperties.Uncompress_dex == nil {
|
||||||
// If the value was not force-set by the user, use reasonable default based on the module.
|
// 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))
|
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())
|
installDir = android.PathForModuleInstall(ctx, "app", a.BaseModuleName())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
a.dexpreopter.isApp = true
|
||||||
a.dexpreopter.installPath = installDir.Join(ctx, a.BaseModuleName()+".apk")
|
a.dexpreopter.installPath = installDir.Join(ctx, a.BaseModuleName()+".apk")
|
||||||
a.dexpreopter.isPresignedPrebuilt = Bool(a.properties.Presigned)
|
a.dexpreopter.isPresignedPrebuilt = Bool(a.properties.Presigned)
|
||||||
a.dexpreopter.uncompressedDex = a.shouldUncompressDex(ctx)
|
a.dexpreopter.uncompressedDex = a.shouldUncompressDex(ctx)
|
||||||
|
@@ -30,6 +30,7 @@ type dexpreopter struct {
|
|||||||
installPath android.InstallPath
|
installPath android.InstallPath
|
||||||
uncompressedDex bool
|
uncompressedDex bool
|
||||||
isSDKLibrary bool
|
isSDKLibrary bool
|
||||||
|
isApp bool
|
||||||
isTest bool
|
isTest bool
|
||||||
isPresignedPrebuilt bool
|
isPresignedPrebuilt bool
|
||||||
|
|
||||||
@@ -38,6 +39,11 @@ type dexpreopter struct {
|
|||||||
classLoaderContexts dexpreopt.ClassLoaderContextMap
|
classLoaderContexts dexpreopt.ClassLoaderContextMap
|
||||||
|
|
||||||
builtInstalled string
|
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 {
|
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,
|
// 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
|
// e.g. in aar.go. This keeps the behaviour that dexpreopting is effectively
|
||||||
// disabled, even if installable is true.
|
// 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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -157,8 +196,6 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Mo
|
|||||||
// The image locations for all Android variants are identical.
|
// The image locations for all Android variants are identical.
|
||||||
imageLocations := bootImage.getAnyAndroidVariant().imageLocations()
|
imageLocations := bootImage.getAnyAndroidVariant().imageLocations()
|
||||||
|
|
||||||
dexLocation := android.InstallPathToOnDevicePath(ctx, d.installPath)
|
|
||||||
|
|
||||||
var profileClassListing android.OptionalPath
|
var profileClassListing android.OptionalPath
|
||||||
var profileBootListing android.OptionalPath
|
var profileBootListing android.OptionalPath
|
||||||
profileIsTextListing := false
|
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{
|
dexpreoptConfig := &dexpreopt.ModuleConfig{
|
||||||
Name: ctx.ModuleName(),
|
Name: ctx.ModuleName(),
|
||||||
DexLocation: dexLocation,
|
DexLocation: dexLocation,
|
||||||
BuildPath: android.PathForModuleOut(ctx, "dexpreopt", ctx.ModuleName()+".jar").OutputPath,
|
BuildPath: buildPath,
|
||||||
DexPath: dexJarFile,
|
DexPath: dexJarFile,
|
||||||
ManifestPath: d.manifestFile,
|
ManifestPath: d.manifestFile,
|
||||||
UncompressedDex: d.uncompressedDex,
|
UncompressedDex: d.uncompressedDex,
|
||||||
@@ -192,6 +230,7 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Mo
|
|||||||
ProfileBootListing: profileBootListing,
|
ProfileBootListing: profileBootListing,
|
||||||
|
|
||||||
EnforceUsesLibraries: d.enforceUsesLibs,
|
EnforceUsesLibraries: d.enforceUsesLibs,
|
||||||
|
ProvidesUsesLibrary: providesUsesLib,
|
||||||
ClassLoaderContexts: d.classLoaderContexts,
|
ClassLoaderContexts: d.classLoaderContexts,
|
||||||
|
|
||||||
Archs: archs,
|
Archs: archs,
|
||||||
|
@@ -148,7 +148,7 @@ func TestDexpreoptEnabled(t *testing.T) {
|
|||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.name, func(t *testing.T) {
|
||||||
ctx, _ := testJava(t, test.bp)
|
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
|
enabled := dexpreopt.Rule != nil
|
||||||
|
|
||||||
if enabled != test.enabled {
|
if enabled != test.enabled {
|
||||||
|
Reference in New Issue
Block a user