blob: 15f11e11c2cb4452e95e9841922aa65213164d7e [file] [log] [blame]
Colin Cross44df5812019-02-15 23:06:46 -08001// Copyright 2019 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package java
16
17import (
Roshan Pius9b51a402019-11-21 12:36:53 -080018 "fmt"
Colin Cross44df5812019-02-15 23:06:46 -080019 "path/filepath"
20 "strings"
Colin Cross2d00f0d2019-05-09 21:50:00 -070021
22 "android/soong/android"
23 "android/soong/dexpreopt"
Colin Cross44df5812019-02-15 23:06:46 -080024)
25
26// dexpreoptGlobalConfig returns the global dexpreopt.config. It is loaded once the first time it is called for any
27// ctx.Config(), and returns the same data for all future calls with the same ctx.Config(). A value can be inserted
28// for tests using setDexpreoptTestGlobalConfig.
29func dexpreoptGlobalConfig(ctx android.PathContext) dexpreopt.GlobalConfig {
Colin Cross2d00f0d2019-05-09 21:50:00 -070030 return dexpreoptGlobalConfigRaw(ctx).global
31}
32
33type globalConfigAndRaw struct {
34 global dexpreopt.GlobalConfig
35 data []byte
36}
37
38func dexpreoptGlobalConfigRaw(ctx android.PathContext) globalConfigAndRaw {
Colin Cross44df5812019-02-15 23:06:46 -080039 return ctx.Config().Once(dexpreoptGlobalConfigKey, func() interface{} {
40 if f := ctx.Config().DexpreoptGlobalConfig(); f != "" {
41 ctx.AddNinjaFileDeps(f)
Colin Cross2d00f0d2019-05-09 21:50:00 -070042 globalConfig, data, err := dexpreopt.LoadGlobalConfig(ctx, f)
Colin Cross44df5812019-02-15 23:06:46 -080043 if err != nil {
44 panic(err)
45 }
Colin Cross2d00f0d2019-05-09 21:50:00 -070046 return globalConfigAndRaw{globalConfig, data}
Colin Cross44df5812019-02-15 23:06:46 -080047 }
48
49 // No global config filename set, see if there is a test config set
50 return ctx.Config().Once(dexpreoptTestGlobalConfigKey, func() interface{} {
51 // Nope, return a config with preopting disabled
Colin Cross2d00f0d2019-05-09 21:50:00 -070052 return globalConfigAndRaw{dexpreopt.GlobalConfig{
Mathieu Chartier6adeee12019-06-26 10:01:36 -070053 DisablePreopt: true,
54 DisableGenerateProfile: true,
Colin Cross2d00f0d2019-05-09 21:50:00 -070055 }, nil}
Colin Cross44df5812019-02-15 23:06:46 -080056 })
Colin Cross2d00f0d2019-05-09 21:50:00 -070057 }).(globalConfigAndRaw)
Colin Cross44df5812019-02-15 23:06:46 -080058}
59
60// setDexpreoptTestGlobalConfig sets a GlobalConfig that future calls to dexpreoptGlobalConfig will return. It must
61// be called before the first call to dexpreoptGlobalConfig for the config.
62func setDexpreoptTestGlobalConfig(config android.Config, globalConfig dexpreopt.GlobalConfig) {
Colin Cross2d00f0d2019-05-09 21:50:00 -070063 config.Once(dexpreoptTestGlobalConfigKey, func() interface{} { return globalConfigAndRaw{globalConfig, nil} })
Colin Cross44df5812019-02-15 23:06:46 -080064}
65
66var dexpreoptGlobalConfigKey = android.NewOnceKey("DexpreoptGlobalConfig")
67var dexpreoptTestGlobalConfigKey = android.NewOnceKey("TestDexpreoptGlobalConfig")
68
Roshan Pius9b51a402019-11-21 12:36:53 -080069// Expected format for apexJarValue = <apex name>:<jar name>
70func splitApexJarPair(apexJarValue string) (string, string) {
71 var apexJarPair []string = strings.SplitN(apexJarValue, ":", 2)
72 if apexJarPair == nil || len(apexJarPair) != 2 {
73 panic(fmt.Errorf("malformed apexJarValue: %q, expected format: <apex>:<jar>",
74 apexJarValue))
75 }
76 return apexJarPair[0], apexJarPair[1]
77}
78
Colin Cross44df5812019-02-15 23:06:46 -080079// systemServerClasspath returns the on-device locations of the modules in the system server classpath. It is computed
80// once the first time it is called for any ctx.Config(), and returns the same slice for all future calls with the same
81// ctx.Config().
82func systemServerClasspath(ctx android.PathContext) []string {
83 return ctx.Config().OnceStringSlice(systemServerClasspathKey, func() []string {
84 global := dexpreoptGlobalConfig(ctx)
85
86 var systemServerClasspathLocations []string
87 for _, m := range global.SystemServerJars {
88 systemServerClasspathLocations = append(systemServerClasspathLocations,
89 filepath.Join("/system/framework", m+".jar"))
90 }
Roshan Pius9b51a402019-11-21 12:36:53 -080091 for _, m := range global.UpdatableSystemServerJars {
92 apex, jar := splitApexJarPair(m)
93 systemServerClasspathLocations = append(systemServerClasspathLocations,
94 filepath.Join("/apex", apex, "javalib", jar + ".jar"))
95 }
Colin Cross44df5812019-02-15 23:06:46 -080096 return systemServerClasspathLocations
97 })
98}
99
100var systemServerClasspathKey = android.NewOnceKey("systemServerClasspath")
101
Colin Crossc11e0c52019-05-08 15:18:22 -0700102// dexpreoptTargets returns the list of targets that are relevant to dexpreopting, which excludes architectures
103// supported through native bridge.
104func dexpreoptTargets(ctx android.PathContext) []android.Target {
105 var targets []android.Target
Colin Cross3b19f5d2019-09-17 14:45:31 -0700106 for _, target := range ctx.Config().Targets[android.Android] {
Colin Crossc11e0c52019-05-08 15:18:22 -0700107 if target.NativeBridge == android.NativeBridgeDisabled {
108 targets = append(targets, target)
109 }
110 }
111
112 return targets
113}
114
Jiyong Park0b238752019-10-29 11:23:10 +0900115func stemOf(moduleName string) string {
116 // b/139391334: the stem of framework-minus-apex is framework
117 // This is hard coded here until we find a good way to query the stem
118 // of a module before any other mutators are run
119 if moduleName == "framework-minus-apex" {
120 return "framework"
121 }
122 return moduleName
123}
124
Ulyana Trafimovichde534412019-11-08 10:51:01 +0000125// Construct a variant of the global config for dexpreopted bootclasspath jars. The variants differ
126// in the list of input jars (libcore, framework, or both), in the naming scheme for the dexpreopt
127// files (ART recognizes "apex" names as special), and whether to include a zip archive.
128//
129// 'name' is a string unique for each profile (used in directory names and ninja rule names)
130// 'stem' is the basename of the image: the resulting filenames are <stem>[-<jar>].{art,oat,vdex}.
131func getBootImageConfig(ctx android.PathContext, key android.OnceKey, name string, stem string,
132 needZip bool, artApexJarsOnly bool) bootImageConfig {
133
Ulya Trafimovich18263382019-10-23 15:56:32 +0100134 return ctx.Config().Once(key, func() interface{} {
Nicolas Geoffray72892f12019-02-22 15:34:40 +0000135 global := dexpreoptGlobalConfig(ctx)
136
Martin Stjernholmcc4b0ad2019-07-05 22:38:25 +0100137 artModules := global.ArtApexJars
Ulyana Trafimovichde534412019-11-08 10:51:01 +0000138 imageModules := artModules
Nicolas Geoffray72892f12019-02-22 15:34:40 +0000139
Nicolas Geoffrayfeef2ef2019-04-30 09:43:22 +0100140 var bootLocations []string
Nicolas Geoffray72892f12019-02-22 15:34:40 +0000141
Martin Stjernholmcc4b0ad2019-07-05 22:38:25 +0100142 for _, m := range artModules {
Nicolas Geoffrayfeef2ef2019-04-30 09:43:22 +0100143 bootLocations = append(bootLocations,
Jiyong Park0b238752019-10-29 11:23:10 +0900144 filepath.Join("/apex/com.android.art/javalib", stemOf(m)+".jar"))
Nicolas Geoffray72892f12019-02-22 15:34:40 +0000145 }
146
Ulyana Trafimovichde534412019-11-08 10:51:01 +0000147 if !artApexJarsOnly {
148 nonFrameworkModules := concat(artModules, global.ProductUpdatableBootModules)
149 frameworkModules := android.RemoveListFromList(global.BootJars, nonFrameworkModules)
150 imageModules = concat(imageModules, frameworkModules)
151
152 for _, m := range frameworkModules {
153 bootLocations = append(bootLocations,
154 filepath.Join("/system/framework", stemOf(m)+".jar"))
155 }
Nicolas Geoffrayfeef2ef2019-04-30 09:43:22 +0100156 }
157
Nicolas Geoffray72892f12019-02-22 15:34:40 +0000158 // The path to bootclasspath dex files needs to be known at module GenerateAndroidBuildAction time, before
159 // the bootclasspath modules have been compiled. Set up known paths for them, the singleton rules will copy
160 // them there.
Jiyong Park0b238752019-10-29 11:23:10 +0900161 // TODO(b/143682396): use module dependencies instead
Nicolas Geoffrayfeef2ef2019-04-30 09:43:22 +0100162 var bootDexPaths android.WritablePaths
163 for _, m := range imageModules {
164 bootDexPaths = append(bootDexPaths,
Nicolas Geoffray24babe32019-10-30 11:26:52 +0000165 android.PathForOutput(ctx, ctx.Config().DeviceName(), "dex_"+name+"jars_input", m+".jar"))
Nicolas Geoffray72892f12019-02-22 15:34:40 +0000166 }
167
Nicolas Geoffray24babe32019-10-30 11:26:52 +0000168 dir := android.PathForOutput(ctx, ctx.Config().DeviceName(), "dex_"+name+"jars")
169 symbolsDir := android.PathForOutput(ctx, ctx.Config().DeviceName(), "dex_"+name+"jars_unstripped")
Ulya Trafimovich18263382019-10-23 15:56:32 +0100170
171 var zip android.WritablePath
172 if needZip {
Ulyana Trafimovichde534412019-11-08 10:51:01 +0000173 zip = dir.Join(ctx, stem+".zip")
Ulya Trafimovich18263382019-10-23 15:56:32 +0100174 }
Nicolas Geoffray72892f12019-02-22 15:34:40 +0000175
Colin Crossc11e0c52019-05-08 15:18:22 -0700176 targets := dexpreoptTargets(ctx)
177
Dan Willemsen0f416782019-06-13 21:44:53 +0000178 imageConfig := bootImageConfig{
Ulya Trafimovich18263382019-10-23 15:56:32 +0100179 name: name,
Ulyana Trafimovichde534412019-11-08 10:51:01 +0000180 stem: stem,
Nicolas Geoffrayfeef2ef2019-04-30 09:43:22 +0100181 modules: imageModules,
182 dexLocations: bootLocations,
183 dexPaths: bootDexPaths,
Nicolas Geoffray72892f12019-02-22 15:34:40 +0000184 dir: dir,
185 symbolsDir: symbolsDir,
Colin Crossc11e0c52019-05-08 15:18:22 -0700186 targets: targets,
Dan Willemsen0f416782019-06-13 21:44:53 +0000187 images: make(map[android.ArchType]android.OutputPath),
188 imagesDeps: make(map[android.ArchType]android.Paths),
Ulya Trafimovich18263382019-10-23 15:56:32 +0100189 zip: zip,
Nicolas Geoffray72892f12019-02-22 15:34:40 +0000190 }
Dan Willemsen0f416782019-06-13 21:44:53 +0000191
192 for _, target := range targets {
193 imageDir := dir.Join(ctx, "system/framework", target.Arch.ArchType.String())
Ulyana Trafimovichde534412019-11-08 10:51:01 +0000194 imageConfig.images[target.Arch.ArchType] = imageDir.Join(ctx, stem+".art")
Dan Willemsen0f416782019-06-13 21:44:53 +0000195
196 imagesDeps := make([]android.Path, 0, len(imageConfig.modules)*3)
197 for _, dep := range imageConfig.moduleFiles(ctx, imageDir, ".art", ".oat", ".vdex") {
198 imagesDeps = append(imagesDeps, dep)
199 }
200 imageConfig.imagesDeps[target.Arch.ArchType] = imagesDeps
201 }
202
203 return imageConfig
Nicolas Geoffray72892f12019-02-22 15:34:40 +0000204 }).(bootImageConfig)
205}
206
Ulyana Trafimovichde534412019-11-08 10:51:01 +0000207// Default config is the one that goes in the system image. It includes both libcore and framework.
Ulya Trafimovich18263382019-10-23 15:56:32 +0100208var defaultBootImageConfigKey = android.NewOnceKey("defaultBootImageConfig")
Ulyana Trafimovich66b3e992019-11-06 17:20:49 +0000209
Ulyana Trafimovichbf0e4762019-11-07 16:12:13 +0000210func defaultBootImageConfig(ctx android.PathContext) bootImageConfig {
Ulyana Trafimovichde534412019-11-08 10:51:01 +0000211 return getBootImageConfig(ctx, defaultBootImageConfigKey, "boot", "boot", true, false)
Ulyana Trafimovich66b3e992019-11-06 17:20:49 +0000212}
213
Ulyana Trafimovichde534412019-11-08 10:51:01 +0000214// Apex config is used for the JIT-zygote experiment. It includes both libcore and framework, but AOT-compiles only libcore.
215var apexBootImageConfigKey = android.NewOnceKey("apexBootImageConfig")
216
Ulyana Trafimovichbf0e4762019-11-07 16:12:13 +0000217func apexBootImageConfig(ctx android.PathContext) bootImageConfig {
Ulyana Trafimovichde534412019-11-08 10:51:01 +0000218 return getBootImageConfig(ctx, apexBootImageConfigKey, "apex", "apex", false, false)
219}
220
221// ART config is the one used for the ART apex. It includes only libcore.
222var artBootImageConfigKey = android.NewOnceKey("artBootImageConfig")
223
224func artBootImageConfig(ctx android.PathContext) bootImageConfig {
225 return getBootImageConfig(ctx, artBootImageConfigKey, "art", "boot", false, true)
Ulya Trafimovich18263382019-10-23 15:56:32 +0100226}
227
Colin Cross44df5812019-02-15 23:06:46 -0800228func defaultBootclasspath(ctx android.PathContext) []string {
229 return ctx.Config().OnceStringSlice(defaultBootclasspathKey, func() []string {
230 global := dexpreoptGlobalConfig(ctx)
231 image := defaultBootImageConfig(ctx)
232 bootclasspath := append(copyOf(image.dexLocations), global.ProductUpdatableBootLocations...)
233 return bootclasspath
234 })
235}
236
237var defaultBootclasspathKey = android.NewOnceKey("defaultBootclasspath")
238
239var copyOf = android.CopyOf
240
241func init() {
242 android.RegisterMakeVarsProvider(pctx, dexpreoptConfigMakevars)
243}
244
245func dexpreoptConfigMakevars(ctx android.MakeVarsContext) {
246 ctx.Strict("PRODUCT_BOOTCLASSPATH", strings.Join(defaultBootclasspath(ctx), ":"))
Nicolas Geoffray07b40072019-02-22 16:57:42 +0000247 ctx.Strict("PRODUCT_DEX2OAT_BOOTCLASSPATH", strings.Join(defaultBootImageConfig(ctx).dexLocations, ":"))
Colin Cross44df5812019-02-15 23:06:46 -0800248 ctx.Strict("PRODUCT_SYSTEM_SERVER_CLASSPATH", strings.Join(systemServerClasspath(ctx), ":"))
Colin Cross9be41522019-02-20 10:40:13 -0800249
250 ctx.Strict("DEXPREOPT_BOOT_JARS_MODULES", strings.Join(defaultBootImageConfig(ctx).modules, ":"))
Colin Cross44df5812019-02-15 23:06:46 -0800251}