Both default and apex configs are used for dexpreopting bootclasspath jars. The difference between the two configs is in the naming (default paths contain "boot", and apex paths contain "apex"). Another difference is that apex config does not have a zip archive. Test: m Test: `find $ANDROID_BUILD_TOP/out -name '*.art' | sort` returns the same list of files before and after the patch Change-Id: I5b2e8d83ab94fd0b1b3d4dc3f0db243ef70bfb08
204 lines
7.4 KiB
Go
204 lines
7.4 KiB
Go
// Copyright 2019 Google Inc. All rights reserved.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package java
|
|
|
|
import (
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"android/soong/android"
|
|
"android/soong/dexpreopt"
|
|
)
|
|
|
|
// dexpreoptGlobalConfig returns the global dexpreopt.config. It is loaded once the first time it is called for any
|
|
// ctx.Config(), and returns the same data for all future calls with the same ctx.Config(). A value can be inserted
|
|
// for tests using setDexpreoptTestGlobalConfig.
|
|
func dexpreoptGlobalConfig(ctx android.PathContext) dexpreopt.GlobalConfig {
|
|
return dexpreoptGlobalConfigRaw(ctx).global
|
|
}
|
|
|
|
type globalConfigAndRaw struct {
|
|
global dexpreopt.GlobalConfig
|
|
data []byte
|
|
}
|
|
|
|
func dexpreoptGlobalConfigRaw(ctx android.PathContext) globalConfigAndRaw {
|
|
return ctx.Config().Once(dexpreoptGlobalConfigKey, func() interface{} {
|
|
if f := ctx.Config().DexpreoptGlobalConfig(); f != "" {
|
|
ctx.AddNinjaFileDeps(f)
|
|
globalConfig, data, err := dexpreopt.LoadGlobalConfig(ctx, f)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
return globalConfigAndRaw{globalConfig, data}
|
|
}
|
|
|
|
// No global config filename set, see if there is a test config set
|
|
return ctx.Config().Once(dexpreoptTestGlobalConfigKey, func() interface{} {
|
|
// Nope, return a config with preopting disabled
|
|
return globalConfigAndRaw{dexpreopt.GlobalConfig{
|
|
DisablePreopt: true,
|
|
DisableGenerateProfile: true,
|
|
}, nil}
|
|
})
|
|
}).(globalConfigAndRaw)
|
|
}
|
|
|
|
// setDexpreoptTestGlobalConfig sets a GlobalConfig that future calls to dexpreoptGlobalConfig will return. It must
|
|
// be called before the first call to dexpreoptGlobalConfig for the config.
|
|
func setDexpreoptTestGlobalConfig(config android.Config, globalConfig dexpreopt.GlobalConfig) {
|
|
config.Once(dexpreoptTestGlobalConfigKey, func() interface{} { return globalConfigAndRaw{globalConfig, nil} })
|
|
}
|
|
|
|
var dexpreoptGlobalConfigKey = android.NewOnceKey("DexpreoptGlobalConfig")
|
|
var dexpreoptTestGlobalConfigKey = android.NewOnceKey("TestDexpreoptGlobalConfig")
|
|
|
|
// systemServerClasspath returns the on-device locations of the modules in the system server classpath. It is computed
|
|
// once the first time it is called for any ctx.Config(), and returns the same slice for all future calls with the same
|
|
// ctx.Config().
|
|
func systemServerClasspath(ctx android.PathContext) []string {
|
|
return ctx.Config().OnceStringSlice(systemServerClasspathKey, func() []string {
|
|
global := dexpreoptGlobalConfig(ctx)
|
|
|
|
var systemServerClasspathLocations []string
|
|
for _, m := range global.SystemServerJars {
|
|
systemServerClasspathLocations = append(systemServerClasspathLocations,
|
|
filepath.Join("/system/framework", m+".jar"))
|
|
}
|
|
return systemServerClasspathLocations
|
|
})
|
|
}
|
|
|
|
var systemServerClasspathKey = android.NewOnceKey("systemServerClasspath")
|
|
|
|
// dexpreoptTargets returns the list of targets that are relevant to dexpreopting, which excludes architectures
|
|
// supported through native bridge.
|
|
func dexpreoptTargets(ctx android.PathContext) []android.Target {
|
|
var targets []android.Target
|
|
for _, target := range ctx.Config().Targets[android.Android] {
|
|
if target.NativeBridge == android.NativeBridgeDisabled {
|
|
targets = append(targets, target)
|
|
}
|
|
}
|
|
|
|
return targets
|
|
}
|
|
|
|
func getBootImageConfig(ctx android.PathContext, key android.OnceKey, name string,
|
|
needZip bool) bootImageConfig {
|
|
return ctx.Config().Once(key, func() interface{} {
|
|
global := dexpreoptGlobalConfig(ctx)
|
|
|
|
artModules := global.ArtApexJars
|
|
nonFrameworkModules := concat(artModules, global.ProductUpdatableBootModules)
|
|
frameworkModules := android.RemoveListFromList(global.BootJars, nonFrameworkModules)
|
|
imageModules := concat(artModules, frameworkModules)
|
|
|
|
var bootLocations []string
|
|
|
|
for _, m := range artModules {
|
|
bootLocations = append(bootLocations,
|
|
filepath.Join("/apex/com.android.art/javalib", m+".jar"))
|
|
}
|
|
|
|
for _, m := range frameworkModules {
|
|
bootLocations = append(bootLocations,
|
|
filepath.Join("/system/framework", m+".jar"))
|
|
}
|
|
|
|
// The path to bootclasspath dex files needs to be known at module GenerateAndroidBuildAction time, before
|
|
// the bootclasspath modules have been compiled. Set up known paths for them, the singleton rules will copy
|
|
// them there.
|
|
// TODO: use module dependencies instead
|
|
var bootDexPaths android.WritablePaths
|
|
for _, m := range imageModules {
|
|
bootDexPaths = append(bootDexPaths,
|
|
android.PathForOutput(ctx, ctx.Config().DeviceName(), "dex_"+name+"jars_input", m+".jar"))
|
|
}
|
|
|
|
dir := android.PathForOutput(ctx, ctx.Config().DeviceName(), "dex_"+name+"jars")
|
|
symbolsDir := android.PathForOutput(ctx, ctx.Config().DeviceName(), "dex_"+name+"jars_unstripped")
|
|
|
|
var zip android.WritablePath
|
|
if needZip {
|
|
zip = dir.Join(ctx, name+".zip")
|
|
}
|
|
|
|
targets := dexpreoptTargets(ctx)
|
|
|
|
imageConfig := bootImageConfig{
|
|
name: name,
|
|
modules: imageModules,
|
|
dexLocations: bootLocations,
|
|
dexPaths: bootDexPaths,
|
|
dir: dir,
|
|
symbolsDir: symbolsDir,
|
|
targets: targets,
|
|
images: make(map[android.ArchType]android.OutputPath),
|
|
imagesDeps: make(map[android.ArchType]android.Paths),
|
|
zip: zip,
|
|
}
|
|
|
|
for _, target := range targets {
|
|
imageDir := dir.Join(ctx, "system/framework", target.Arch.ArchType.String())
|
|
imageConfig.images[target.Arch.ArchType] = imageDir.Join(ctx, name+".art")
|
|
|
|
imagesDeps := make([]android.Path, 0, len(imageConfig.modules)*3)
|
|
for _, dep := range imageConfig.moduleFiles(ctx, imageDir, ".art", ".oat", ".vdex") {
|
|
imagesDeps = append(imagesDeps, dep)
|
|
}
|
|
imageConfig.imagesDeps[target.Arch.ArchType] = imagesDeps
|
|
}
|
|
|
|
return imageConfig
|
|
}).(bootImageConfig)
|
|
}
|
|
|
|
var defaultBootImageConfigKey = android.NewOnceKey("defaultBootImageConfig")
|
|
var apexBootImageConfigKey = android.NewOnceKey("apexBootImageConfig")
|
|
|
|
func defaultBootImageConfig(ctx android.PathContext) bootImageConfig {
|
|
return getBootImageConfig(ctx, defaultBootImageConfigKey, "boot", true)
|
|
}
|
|
|
|
func apexBootImageConfig(ctx android.PathContext) bootImageConfig {
|
|
return getBootImageConfig(ctx, apexBootImageConfigKey, "apex", false)
|
|
}
|
|
|
|
func defaultBootclasspath(ctx android.PathContext) []string {
|
|
return ctx.Config().OnceStringSlice(defaultBootclasspathKey, func() []string {
|
|
global := dexpreoptGlobalConfig(ctx)
|
|
image := defaultBootImageConfig(ctx)
|
|
bootclasspath := append(copyOf(image.dexLocations), global.ProductUpdatableBootLocations...)
|
|
return bootclasspath
|
|
})
|
|
}
|
|
|
|
var defaultBootclasspathKey = android.NewOnceKey("defaultBootclasspath")
|
|
|
|
var copyOf = android.CopyOf
|
|
|
|
func init() {
|
|
android.RegisterMakeVarsProvider(pctx, dexpreoptConfigMakevars)
|
|
}
|
|
|
|
func dexpreoptConfigMakevars(ctx android.MakeVarsContext) {
|
|
ctx.Strict("PRODUCT_BOOTCLASSPATH", strings.Join(defaultBootclasspath(ctx), ":"))
|
|
ctx.Strict("PRODUCT_DEX2OAT_BOOTCLASSPATH", strings.Join(defaultBootImageConfig(ctx).dexLocations, ":"))
|
|
ctx.Strict("PRODUCT_SYSTEM_SERVER_CLASSPATH", strings.Join(systemServerClasspath(ctx), ":"))
|
|
|
|
ctx.Strict("DEXPREOPT_BOOT_JARS_MODULES", strings.Join(defaultBootImageConfig(ctx).modules, ":"))
|
|
}
|