Merge "Expose "full" dexpreopt.config"
This commit is contained in:
commit
a3693772a6
|
@ -130,7 +130,7 @@ type ModuleConfig struct {
|
||||||
ClassLoaderContexts ClassLoaderContextMap
|
ClassLoaderContexts ClassLoaderContextMap
|
||||||
|
|
||||||
Archs []android.ArchType
|
Archs []android.ArchType
|
||||||
DexPreoptImages []android.Path
|
DexPreoptImages android.Paths
|
||||||
DexPreoptImagesDeps []android.OutputPaths
|
DexPreoptImagesDeps []android.OutputPaths
|
||||||
DexPreoptImageLocations []string
|
DexPreoptImageLocations []string
|
||||||
|
|
||||||
|
@ -259,29 +259,35 @@ func SetTestGlobalConfig(config android.Config, globalConfig *GlobalConfig) {
|
||||||
config.Once(testGlobalConfigOnceKey, func() interface{} { return globalConfigAndRaw{globalConfig, nil} })
|
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
|
// ParseModuleConfig parses a per-module dexpreopt.config file into a
|
||||||
// ModuleConfig struct. It is not used in Soong, which receives a ModuleConfig
|
// 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
|
// 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
|
// from Make to read the module dexpreopt.config written in the Make config
|
||||||
// stage.
|
// stage.
|
||||||
func ParseModuleConfig(ctx android.PathContext, data []byte) (*ModuleConfig, error) {
|
func ParseModuleConfig(ctx android.PathContext, data []byte) (*ModuleConfig, error) {
|
||||||
type ModuleJSONConfig struct {
|
config := moduleJSONConfig{}
|
||||||
*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{}
|
|
||||||
|
|
||||||
err := json.Unmarshal(data, &config)
|
err := json.Unmarshal(data, &config)
|
||||||
if err != nil {
|
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.EnforceUsesLibrariesStatusFile = constructPath(ctx, config.EnforceUsesLibrariesStatusFile)
|
||||||
config.ModuleConfig.ClassLoaderContexts = fromJsonClassLoaderContext(ctx, config.ClassLoaderContexts)
|
config.ModuleConfig.ClassLoaderContexts = fromJsonClassLoaderContext(ctx, config.ClassLoaderContexts)
|
||||||
config.ModuleConfig.DexPreoptImages = constructPaths(ctx, config.DexPreoptImages)
|
config.ModuleConfig.DexPreoptImages = constructPaths(ctx, config.DexPreoptImages)
|
||||||
config.ModuleConfig.DexPreoptImageLocations = config.DexPreoptImageLocations
|
|
||||||
config.ModuleConfig.PreoptBootClassPathDexFiles = constructPaths(ctx, config.PreoptBootClassPathDexFiles)
|
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.
|
// 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
|
return config.ModuleConfig, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteSlimModuleConfigForMake serializes a subset of ModuleConfig into a per-module
|
func pathsListToStringLists(pathsList []android.OutputPaths) [][]string {
|
||||||
// dexpreopt.config JSON file. It is a way to pass dexpreopt information about Soong modules to
|
ret := make([][]string, 0, len(pathsList))
|
||||||
// Make, which is needed when a Make module has a <uses-library> dependency on a Soong module.
|
for _, paths := range pathsList {
|
||||||
func WriteSlimModuleConfigForMake(ctx android.ModuleContext, config *ModuleConfig, path android.WritablePath) {
|
ret = append(ret, paths.Strings())
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
|
}, "", " ")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 {
|
if path == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// JSON representation of the slim module dexpreopt.config.
|
data, err := moduleConfigToJSON(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 {
|
if err != nil {
|
||||||
ctx.ModuleErrorf("failed to JSON marshal module dexpreopt.config: %v", err)
|
ctx.ModuleErrorf("failed to JSON marshal module dexpreopt.config: %v", err)
|
||||||
return
|
return
|
||||||
|
|
|
@ -166,3 +166,20 @@ func TestDexPreoptProfile(t *testing.T) {
|
||||||
t.Errorf("\nwant installs:\n %v\ngot:\n %v", wantInstalls, rule.Installs())
|
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)
|
||||||
|
}
|
||||||
|
|
|
@ -398,6 +398,9 @@ func (app *AndroidApp) AndroidMkEntries() []android.AndroidMkEntries {
|
||||||
if len(app.dexpreopter.builtInstalled) > 0 {
|
if len(app.dexpreopter.builtInstalled) > 0 {
|
||||||
entries.SetString("LOCAL_SOONG_BUILT_INSTALLED", app.dexpreopter.builtInstalled)
|
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 {
|
for _, extra := range app.extraOutputFiles {
|
||||||
install := app.onDeviceDir + "/" + extra.Base()
|
install := app.onDeviceDir + "/" + extra.Base()
|
||||||
entries.AddStrings("LOCAL_SOONG_BUILT_INSTALLED", extra.String()+":"+install)
|
entries.AddStrings("LOCAL_SOONG_BUILT_INSTALLED", extra.String()+":"+install)
|
||||||
|
|
|
@ -41,9 +41,12 @@ type dexpreopter struct {
|
||||||
|
|
||||||
builtInstalled string
|
builtInstalled string
|
||||||
|
|
||||||
// A path to a dexpreopt.config file generated by Soong for libraries that may be used as a
|
// The config is used for two purposes:
|
||||||
// <uses-library> by Make modules. The path is passed to Make via LOCAL_SOONG_DEXPREOPT_CONFIG
|
// - Passing dexpreopt information about libraries from Soong to Make. This is needed when
|
||||||
// variable. If the path is nil, no config is generated (which is the case for apps and tests).
|
// 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
|
configPath android.WritablePath
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,27 +141,13 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Wr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !d.isApp && !d.isTest {
|
// If it is neither app nor test, make config files regardless of its dexpreopt setting.
|
||||||
// Slim dexpreopt config is serialized to dexpreopt.config files and used by
|
// The config files are required for apps defined in make which depend on the lib.
|
||||||
// dex_preopt_config_merger.py to get information about <uses-library> dependencies.
|
// TODO(b/158843648): The config for apps should be generated as well regardless of setting.
|
||||||
// Note that it might be needed even if dexpreopt is disabled for this module.
|
if (d.isApp || d.isTest) && d.dexpreoptDisabled(ctx) {
|
||||||
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) {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
globalSoong := dexpreopt.GetGlobalSoongConfig(ctx)
|
|
||||||
global := dexpreopt.GetGlobalConfig(ctx)
|
global := dexpreopt.GetGlobalConfig(ctx)
|
||||||
|
|
||||||
isSystemServerJar := inList(ctx.ModuleName(), global.SystemServerJars)
|
isSystemServerJar := inList(ctx.ModuleName(), global.SystemServerJars)
|
||||||
|
@ -251,6 +240,15 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Wr
|
||||||
PresignedPrebuilt: d.isPresignedPrebuilt,
|
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)
|
dexpreoptRule, err := dexpreopt.GenerateDexpreoptRule(ctx, globalSoong, global, dexpreoptConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ModuleErrorf("error generating dexpreopt rule: %s", err.Error())
|
ctx.ModuleErrorf("error generating dexpreopt rule: %s", err.Error())
|
||||||
|
|
Loading…
Reference in New Issue