summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dexpreopt/config.go93
-rw-r--r--dexpreopt/dexpreopt_test.go17
-rw-r--r--java/androidmk.go3
-rw-r--r--java/dexpreopt.go40
4 files changed, 90 insertions, 63 deletions
diff --git a/dexpreopt/config.go b/dexpreopt/config.go
index 26ff5baab..151f032fb 100644
--- a/dexpreopt/config.go
+++ b/dexpreopt/config.go
@@ -130,7 +130,7 @@ type ModuleConfig struct {
ClassLoaderContexts ClassLoaderContextMap
Archs []android.ArchType
- DexPreoptImages []android.Path
+ DexPreoptImages android.Paths
DexPreoptImagesDeps []android.OutputPaths
DexPreoptImageLocations []string
@@ -259,29 +259,35 @@ func SetTestGlobalConfig(config android.Config, globalConfig *GlobalConfig) {
config.Once(testGlobalConfigOnceKey, func() interface{} { return globalConfigAndRaw{globalConfig, nil} })
}
+// This struct is required to convert ModuleConfig from/to JSON.
+// The types of fields in ModuleConfig are not convertible,
+// so moduleJSONConfig has those fields as a convertible type.
+type moduleJSONConfig struct {
+ *ModuleConfig
+
+ BuildPath string
+ DexPath string
+ ManifestPath string
+
+ ProfileClassListing string
+ ProfileBootListing string
+
+ EnforceUsesLibrariesStatusFile string
+ ClassLoaderContexts jsonClassLoaderContextMap
+
+ DexPreoptImages []string
+ DexPreoptImagesDeps [][]string
+
+ PreoptBootClassPathDexFiles []string
+}
+
// 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
-
- // Copies of entries in ModuleConfig that are not constructable without extra parameters. They will be
- // used to construct the real value manually below.
- BuildPath string
- DexPath string
- ManifestPath string
- ProfileClassListing string
- EnforceUsesLibrariesStatusFile string
- ClassLoaderContexts jsonClassLoaderContextMap
- DexPreoptImages []string
- DexPreoptImageLocations []string
- PreoptBootClassPathDexFiles []string
- }
-
- config := ModuleJSONConfig{}
+ config := moduleJSONConfig{}
err := json.Unmarshal(data, &config)
if err != nil {
@@ -296,7 +302,6 @@ func ParseModuleConfig(ctx android.PathContext, data []byte) (*ModuleConfig, err
config.ModuleConfig.EnforceUsesLibrariesStatusFile = constructPath(ctx, config.EnforceUsesLibrariesStatusFile)
config.ModuleConfig.ClassLoaderContexts = fromJsonClassLoaderContext(ctx, config.ClassLoaderContexts)
config.ModuleConfig.DexPreoptImages = constructPaths(ctx, config.DexPreoptImages)
- config.ModuleConfig.DexPreoptImageLocations = config.DexPreoptImageLocations
config.ModuleConfig.PreoptBootClassPathDexFiles = constructPaths(ctx, config.PreoptBootClassPathDexFiles)
// This needs to exist, but dependencies are already handled in Make, so we don't need to pass them through JSON.
@@ -305,34 +310,38 @@ 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
+func pathsListToStringLists(pathsList []android.OutputPaths) [][]string {
+ ret := make([][]string, 0, len(pathsList))
+ for _, paths := range pathsList {
+ ret = append(ret, paths.Strings())
}
+ return ret
+}
- // JSON representation of the slim module dexpreopt.config.
- type slimModuleJSONConfig struct {
- Name string
- DexLocation string
- BuildPath string
- EnforceUsesLibraries bool
- ProvidesUsesLibrary string
- ClassLoaderContexts jsonClassLoaderContextMap
- }
+func moduleConfigToJSON(config *ModuleConfig) ([]byte, error) {
+ return json.MarshalIndent(&moduleJSONConfig{
+ BuildPath: config.BuildPath.String(),
+ DexPath: config.DexPath.String(),
+ ManifestPath: config.ManifestPath.String(),
+ ProfileClassListing: config.ProfileClassListing.String(),
+ ProfileBootListing: config.ProfileBootListing.String(),
+ EnforceUsesLibrariesStatusFile: config.EnforceUsesLibrariesStatusFile.String(),
+ ClassLoaderContexts: toJsonClassLoaderContext(config.ClassLoaderContexts),
+ DexPreoptImages: config.DexPreoptImages.Strings(),
+ DexPreoptImagesDeps: pathsListToStringLists(config.DexPreoptImagesDeps),
+ PreoptBootClassPathDexFiles: config.PreoptBootClassPathDexFiles.Strings(),
+ ModuleConfig: config,
+ }, "", " ")
+}
- jsonConfig := &slimModuleJSONConfig{
- Name: config.Name,
- DexLocation: config.DexLocation,
- BuildPath: config.BuildPath.String(),
- EnforceUsesLibraries: config.EnforceUsesLibraries,
- ProvidesUsesLibrary: config.ProvidesUsesLibrary,
- ClassLoaderContexts: toJsonClassLoaderContext(config.ClassLoaderContexts),
+// WriteModuleConfig serializes a ModuleConfig into a per-module dexpreopt.config JSON file.
+// These config files are used for post-processing.
+func WriteModuleConfig(ctx android.ModuleContext, config *ModuleConfig, path android.WritablePath) {
+ if path == nil {
+ return
}
- data, err := json.MarshalIndent(jsonConfig, "", " ")
+ data, err := moduleConfigToJSON(config)
if err != nil {
ctx.ModuleErrorf("failed to JSON marshal module dexpreopt.config: %v", err)
return
diff --git a/dexpreopt/dexpreopt_test.go b/dexpreopt/dexpreopt_test.go
index 12df36b6f..cd7551c8d 100644
--- a/dexpreopt/dexpreopt_test.go
+++ b/dexpreopt/dexpreopt_test.go
@@ -166,3 +166,20 @@ func TestDexPreoptProfile(t *testing.T) {
t.Errorf("\nwant installs:\n %v\ngot:\n %v", wantInstalls, rule.Installs())
}
}
+
+func TestDexPreoptConfigToJson(t *testing.T) {
+ config := android.TestConfig("out", nil, "", nil)
+ ctx := android.BuilderContextForTesting(config)
+ module := testSystemModuleConfig(ctx, "test")
+ data, err := moduleConfigToJSON(module)
+ if err != nil {
+ t.Errorf("Failed to convert module config data to JSON, %v", err)
+ }
+ parsed, err := ParseModuleConfig(ctx, data)
+ if err != nil {
+ t.Errorf("Failed to parse JSON, %v", err)
+ }
+ before := fmt.Sprintf("%v", module)
+ after := fmt.Sprintf("%v", parsed)
+ android.AssertStringEquals(t, "The result must be the same as the original after marshalling and unmarshalling it.", before, after)
+}
diff --git a/java/androidmk.go b/java/androidmk.go
index 4e594a2fa..015454464 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -398,6 +398,9 @@ func (app *AndroidApp) AndroidMkEntries() []android.AndroidMkEntries {
if len(app.dexpreopter.builtInstalled) > 0 {
entries.SetString("LOCAL_SOONG_BUILT_INSTALLED", app.dexpreopter.builtInstalled)
}
+ if app.dexpreopter.configPath != nil {
+ entries.SetPath("LOCAL_SOONG_DEXPREOPT_CONFIG", app.dexpreopter.configPath)
+ }
for _, extra := range app.extraOutputFiles {
install := app.onDeviceDir + "/" + extra.Base()
entries.AddStrings("LOCAL_SOONG_BUILT_INSTALLED", extra.String()+":"+install)
diff --git a/java/dexpreopt.go b/java/dexpreopt.go
index 3571590db..d00d74b8c 100644
--- a/java/dexpreopt.go
+++ b/java/dexpreopt.go
@@ -41,9 +41,12 @@ type dexpreopter struct {
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).
+ // The config is used for two purposes:
+ // - Passing dexpreopt information about libraries from Soong to Make. This is needed when
+ // a <uses-library> is defined in Android.bp, but used in Android.mk (see dex_preopt_config_merger.py).
+ // Note that dexpreopt.config might be needed even if dexpreopt is disabled for the library itself.
+ // - Dexpreopt post-processing (using dexpreopt artifacts from a prebuilt system image to incrementally
+ // dexpreopt another partition).
configPath android.WritablePath
}
@@ -138,27 +141,13 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Wr
}
}
- 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,
- 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) {
+ // If it is neither app nor test, make config files regardless of its dexpreopt setting.
+ // The config files are required for apps defined in make which depend on the lib.
+ // TODO(b/158843648): The config for apps should be generated as well regardless of setting.
+ if (d.isApp || d.isTest) && d.dexpreoptDisabled(ctx) {
return
}
- globalSoong := dexpreopt.GetGlobalSoongConfig(ctx)
global := dexpreopt.GetGlobalConfig(ctx)
isSystemServerJar := inList(ctx.ModuleName(), global.SystemServerJars)
@@ -251,6 +240,15 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Wr
PresignedPrebuilt: d.isPresignedPrebuilt,
}
+ d.configPath = android.PathForModuleOut(ctx, "dexpreopt", "dexpreopt.config")
+ dexpreopt.WriteModuleConfig(ctx, dexpreoptConfig, d.configPath)
+
+ if d.dexpreoptDisabled(ctx) {
+ return
+ }
+
+ globalSoong := dexpreopt.GetGlobalSoongConfig(ctx)
+
dexpreoptRule, err := dexpreopt.GenerateDexpreoptRule(ctx, globalSoong, global, dexpreoptConfig)
if err != nil {
ctx.ModuleErrorf("error generating dexpreopt rule: %s", err.Error())