Loading dexpreopt/config.go +51 −42 Original line number Diff line number Diff line Loading @@ -130,7 +130,7 @@ type ModuleConfig struct { ClassLoaderContexts ClassLoaderContextMap Archs []android.ArchType DexPreoptImages []android.Path DexPreoptImages android.Paths DexPreoptImagesDeps []android.OutputPaths DexPreoptImageLocations []string Loading Loading @@ -259,29 +259,35 @@ 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 { // 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 // 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 ProfileBootListing string EnforceUsesLibrariesStatusFile string ClassLoaderContexts jsonClassLoaderContextMap DexPreoptImages []string DexPreoptImageLocations []string DexPreoptImagesDeps [][]string PreoptBootClassPathDexFiles []string } config := ModuleJSONConfig{} // 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) { config := moduleJSONConfig{} err := json.Unmarshal(data, &config) if err != nil { Loading @@ -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. Loading @@ -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()) } // JSON representation of the slim module dexpreopt.config. type slimModuleJSONConfig struct { Name string DexLocation string BuildPath string EnforceUsesLibraries bool ProvidesUsesLibrary string ClassLoaderContexts jsonClassLoaderContextMap return ret } jsonConfig := &slimModuleJSONConfig{ Name: config.Name, DexLocation: config.DexLocation, func moduleConfigToJSON(config *ModuleConfig) ([]byte, error) { return json.MarshalIndent(&moduleJSONConfig{ BuildPath: config.BuildPath.String(), EnforceUsesLibraries: config.EnforceUsesLibraries, ProvidesUsesLibrary: config.ProvidesUsesLibrary, 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, }, "", " ") } // 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 Loading dexpreopt/dexpreopt_test.go +17 −0 Original line number Diff line number Diff line Loading @@ -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) } java/androidmk.go +3 −0 Original line number Diff line number Diff line Loading @@ -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) Loading java/dexpreopt.go +19 −21 Original line number Diff line number Diff line Loading @@ -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 } Loading Loading @@ -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) Loading Loading @@ -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()) Loading Loading
dexpreopt/config.go +51 −42 Original line number Diff line number Diff line Loading @@ -130,7 +130,7 @@ type ModuleConfig struct { ClassLoaderContexts ClassLoaderContextMap Archs []android.ArchType DexPreoptImages []android.Path DexPreoptImages android.Paths DexPreoptImagesDeps []android.OutputPaths DexPreoptImageLocations []string Loading Loading @@ -259,29 +259,35 @@ 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 { // 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 // 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 ProfileBootListing string EnforceUsesLibrariesStatusFile string ClassLoaderContexts jsonClassLoaderContextMap DexPreoptImages []string DexPreoptImageLocations []string DexPreoptImagesDeps [][]string PreoptBootClassPathDexFiles []string } config := ModuleJSONConfig{} // 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) { config := moduleJSONConfig{} err := json.Unmarshal(data, &config) if err != nil { Loading @@ -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. Loading @@ -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()) } // JSON representation of the slim module dexpreopt.config. type slimModuleJSONConfig struct { Name string DexLocation string BuildPath string EnforceUsesLibraries bool ProvidesUsesLibrary string ClassLoaderContexts jsonClassLoaderContextMap return ret } jsonConfig := &slimModuleJSONConfig{ Name: config.Name, DexLocation: config.DexLocation, func moduleConfigToJSON(config *ModuleConfig) ([]byte, error) { return json.MarshalIndent(&moduleJSONConfig{ BuildPath: config.BuildPath.String(), EnforceUsesLibraries: config.EnforceUsesLibraries, ProvidesUsesLibrary: config.ProvidesUsesLibrary, 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, }, "", " ") } // 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 Loading
dexpreopt/dexpreopt_test.go +17 −0 Original line number Diff line number Diff line Loading @@ -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) }
java/androidmk.go +3 −0 Original line number Diff line number Diff line Loading @@ -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) Loading
java/dexpreopt.go +19 −21 Original line number Diff line number Diff line Loading @@ -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 } Loading Loading @@ -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) Loading Loading @@ -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()) Loading