1// 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 ( 18 "android/soong/android" 19 "android/soong/dexpreopt" 20 "path/filepath" 21 "strings" 22) 23 24// dexpreoptGlobalConfig returns the global dexpreopt.config. It is loaded once the first time it is called for any 25// ctx.Config(), and returns the same data for all future calls with the same ctx.Config(). A value can be inserted 26// for tests using setDexpreoptTestGlobalConfig. 27func dexpreoptGlobalConfig(ctx android.PathContext) dexpreopt.GlobalConfig { 28 return ctx.Config().Once(dexpreoptGlobalConfigKey, func() interface{} { 29 if f := ctx.Config().DexpreoptGlobalConfig(); f != "" { 30 ctx.AddNinjaFileDeps(f) 31 globalConfig, err := dexpreopt.LoadGlobalConfig(ctx, f) 32 if err != nil { 33 panic(err) 34 } 35 return globalConfig 36 } 37 38 // No global config filename set, see if there is a test config set 39 return ctx.Config().Once(dexpreoptTestGlobalConfigKey, func() interface{} { 40 // Nope, return a config with preopting disabled 41 return dexpreopt.GlobalConfig{ 42 DisablePreopt: true, 43 } 44 }) 45 }).(dexpreopt.GlobalConfig) 46} 47 48// setDexpreoptTestGlobalConfig sets a GlobalConfig that future calls to dexpreoptGlobalConfig will return. It must 49// be called before the first call to dexpreoptGlobalConfig for the config. 50func setDexpreoptTestGlobalConfig(config android.Config, globalConfig dexpreopt.GlobalConfig) { 51 config.Once(dexpreoptTestGlobalConfigKey, func() interface{} { return globalConfig }) 52} 53 54var dexpreoptGlobalConfigKey = android.NewOnceKey("DexpreoptGlobalConfig") 55var dexpreoptTestGlobalConfigKey = android.NewOnceKey("TestDexpreoptGlobalConfig") 56 57// systemServerClasspath returns the on-device locations of the modules in the system server classpath. It is computed 58// once the first time it is called for any ctx.Config(), and returns the same slice for all future calls with the same 59// ctx.Config(). 60func systemServerClasspath(ctx android.PathContext) []string { 61 return ctx.Config().OnceStringSlice(systemServerClasspathKey, func() []string { 62 global := dexpreoptGlobalConfig(ctx) 63 64 var systemServerClasspathLocations []string 65 for _, m := range global.SystemServerJars { 66 systemServerClasspathLocations = append(systemServerClasspathLocations, 67 filepath.Join("/system/framework", m+".jar")) 68 } 69 return systemServerClasspathLocations 70 }) 71} 72 73var systemServerClasspathKey = android.NewOnceKey("systemServerClasspath") 74 75// defaultBootImageConfig returns the bootImageConfig that will be used to dexpreopt modules. It is computed once the 76// first time it is called for any ctx.Config(), and returns the same slice for all future calls with the same 77// ctx.Config(). 78func defaultBootImageConfig(ctx android.PathContext) bootImageConfig { 79 return ctx.Config().Once(defaultBootImageConfigKey, func() interface{} { 80 global := dexpreoptGlobalConfig(ctx) 81 82 runtimeModules := global.RuntimeApexJars 83 nonFrameworkModules := concat(runtimeModules, global.ProductUpdatableBootModules) 84 frameworkModules := android.RemoveListFromList(global.BootJars, nonFrameworkModules) 85 86 var nonUpdatableBootModules []string 87 var nonUpdatableBootLocations []string 88 89 for _, m := range runtimeModules { 90 nonUpdatableBootModules = append(nonUpdatableBootModules, m) 91 nonUpdatableBootLocations = append(nonUpdatableBootLocations, 92 filepath.Join("/apex/com.android.runtime/javalib", m+".jar")) 93 } 94 95 for _, m := range frameworkModules { 96 nonUpdatableBootModules = append(nonUpdatableBootModules, m) 97 nonUpdatableBootLocations = append(nonUpdatableBootLocations, 98 filepath.Join("/system/framework", m+".jar")) 99 } 100 101 // The path to bootclasspath dex files needs to be known at module GenerateAndroidBuildAction time, before 102 // the bootclasspath modules have been compiled. Set up known paths for them, the singleton rules will copy 103 // them there. 104 // TODO: use module dependencies instead 105 var nonUpdatableBootDexPaths android.WritablePaths 106 for _, m := range nonUpdatableBootModules { 107 nonUpdatableBootDexPaths = append(nonUpdatableBootDexPaths, 108 android.PathForOutput(ctx, ctx.Config().DeviceName(), "dex_bootjars_input", m+".jar")) 109 } 110 111 dir := android.PathForOutput(ctx, ctx.Config().DeviceName(), "dex_bootjars") 112 symbolsDir := android.PathForOutput(ctx, ctx.Config().DeviceName(), "dex_bootjars_unstripped") 113 images := make(map[android.ArchType]android.OutputPath) 114 115 for _, target := range ctx.Config().Targets[android.Android] { 116 images[target.Arch.ArchType] = dir.Join(ctx, 117 "system/framework", target.Arch.ArchType.String()).Join(ctx, "boot.art") 118 } 119 120 return bootImageConfig{ 121 name: "boot", 122 modules: nonUpdatableBootModules, 123 dexLocations: nonUpdatableBootLocations, 124 dexPaths: nonUpdatableBootDexPaths, 125 dir: dir, 126 symbolsDir: symbolsDir, 127 images: images, 128 } 129 }).(bootImageConfig) 130} 131 132var defaultBootImageConfigKey = android.NewOnceKey("defaultBootImageConfig") 133 134func apexBootImageConfig(ctx android.PathContext) bootImageConfig { 135 return ctx.Config().Once(apexBootImageConfigKey, func() interface{} { 136 global := dexpreoptGlobalConfig(ctx) 137 138 runtimeModules := global.RuntimeApexJars 139 nonFrameworkModules := concat(runtimeModules, global.ProductUpdatableBootModules) 140 frameworkModules := android.RemoveListFromList(global.BootJars, nonFrameworkModules) 141 imageModules := concat(runtimeModules, frameworkModules) 142 143 var bootLocations []string 144 145 for _, m := range runtimeModules { 146 bootLocations = append(bootLocations, 147 filepath.Join("/apex/com.android.runtime/javalib", m+".jar")) 148 } 149 150 for _, m := range frameworkModules { 151 bootLocations = append(bootLocations, 152 filepath.Join("/system/framework", m+".jar")) 153 } 154 155 // The path to bootclasspath dex files needs to be known at module GenerateAndroidBuildAction time, before 156 // the bootclasspath modules have been compiled. Set up known paths for them, the singleton rules will copy 157 // them there. 158 // TODO: use module dependencies instead 159 var bootDexPaths android.WritablePaths 160 for _, m := range imageModules { 161 bootDexPaths = append(bootDexPaths, 162 android.PathForOutput(ctx, ctx.Config().DeviceName(), "dex_apexjars_input", m+".jar")) 163 } 164 165 dir := android.PathForOutput(ctx, ctx.Config().DeviceName(), "dex_apexjars") 166 symbolsDir := android.PathForOutput(ctx, ctx.Config().DeviceName(), "dex_apexjars_unstripped") 167 images := make(map[android.ArchType]android.OutputPath) 168 169 for _, target := range ctx.Config().Targets[android.Android] { 170 images[target.Arch.ArchType] = dir.Join(ctx, 171 "system/framework", target.Arch.ArchType.String(), "apex.art") 172 } 173 174 return bootImageConfig{ 175 name: "apex", 176 modules: imageModules, 177 dexLocations: bootLocations, 178 dexPaths: bootDexPaths, 179 dir: dir, 180 symbolsDir: symbolsDir, 181 images: images, 182 } 183 }).(bootImageConfig) 184} 185 186var apexBootImageConfigKey = android.NewOnceKey("apexBootImageConfig") 187 188func defaultBootclasspath(ctx android.PathContext) []string { 189 return ctx.Config().OnceStringSlice(defaultBootclasspathKey, func() []string { 190 global := dexpreoptGlobalConfig(ctx) 191 image := defaultBootImageConfig(ctx) 192 bootclasspath := append(copyOf(image.dexLocations), global.ProductUpdatableBootLocations...) 193 return bootclasspath 194 }) 195} 196 197var defaultBootclasspathKey = android.NewOnceKey("defaultBootclasspath") 198 199var copyOf = android.CopyOf 200 201func init() { 202 android.RegisterMakeVarsProvider(pctx, dexpreoptConfigMakevars) 203} 204 205func dexpreoptConfigMakevars(ctx android.MakeVarsContext) { 206 ctx.Strict("PRODUCT_BOOTCLASSPATH", strings.Join(defaultBootclasspath(ctx), ":")) 207 ctx.Strict("PRODUCT_DEX2OAT_BOOTCLASSPATH", strings.Join(defaultBootImageConfig(ctx).dexLocations, ":")) 208 ctx.Strict("PRODUCT_SYSTEM_SERVER_CLASSPATH", strings.Join(systemServerClasspath(ctx), ":")) 209 210 ctx.Strict("DEXPREOPT_BOOT_JARS_MODULES", strings.Join(defaultBootImageConfig(ctx).modules, ":")) 211} 212