1*333d2b36SAndroid Build Coastguard Worker// Copyright 2019 Google Inc. All rights reserved. 2*333d2b36SAndroid Build Coastguard Worker// 3*333d2b36SAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License"); 4*333d2b36SAndroid Build Coastguard Worker// you may not use this file except in compliance with the License. 5*333d2b36SAndroid Build Coastguard Worker// You may obtain a copy of the License at 6*333d2b36SAndroid Build Coastguard Worker// 7*333d2b36SAndroid Build Coastguard Worker// http://www.apache.org/licenses/LICENSE-2.0 8*333d2b36SAndroid Build Coastguard Worker// 9*333d2b36SAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software 10*333d2b36SAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS, 11*333d2b36SAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*333d2b36SAndroid Build Coastguard Worker// See the License for the specific language governing permissions and 13*333d2b36SAndroid Build Coastguard Worker// limitations under the License. 14*333d2b36SAndroid Build Coastguard Worker 15*333d2b36SAndroid Build Coastguard Workerpackage java 16*333d2b36SAndroid Build Coastguard Worker 17*333d2b36SAndroid Build Coastguard Workerimport ( 18*333d2b36SAndroid Build Coastguard Worker "path/filepath" 19*333d2b36SAndroid Build Coastguard Worker "strings" 20*333d2b36SAndroid Build Coastguard Worker 21*333d2b36SAndroid Build Coastguard Worker "android/soong/android" 22*333d2b36SAndroid Build Coastguard Worker "android/soong/dexpreopt" 23*333d2b36SAndroid Build Coastguard Worker) 24*333d2b36SAndroid Build Coastguard Worker 25*333d2b36SAndroid Build Coastguard Worker// dexpreoptTargets returns the list of targets that are relevant to dexpreopting, which excludes architectures 26*333d2b36SAndroid Build Coastguard Worker// supported through native bridge. 27*333d2b36SAndroid Build Coastguard Workerfunc dexpreoptTargets(ctx android.PathContext) []android.Target { 28*333d2b36SAndroid Build Coastguard Worker var targets []android.Target 29*333d2b36SAndroid Build Coastguard Worker for _, target := range ctx.Config().Targets[android.Android] { 30*333d2b36SAndroid Build Coastguard Worker if target.NativeBridge == android.NativeBridgeDisabled { 31*333d2b36SAndroid Build Coastguard Worker targets = append(targets, target) 32*333d2b36SAndroid Build Coastguard Worker } 33*333d2b36SAndroid Build Coastguard Worker } 34*333d2b36SAndroid Build Coastguard Worker // We may also need the images on host in order to run host-based tests. 35*333d2b36SAndroid Build Coastguard Worker for _, target := range ctx.Config().Targets[ctx.Config().BuildOS] { 36*333d2b36SAndroid Build Coastguard Worker targets = append(targets, target) 37*333d2b36SAndroid Build Coastguard Worker } 38*333d2b36SAndroid Build Coastguard Worker 39*333d2b36SAndroid Build Coastguard Worker return targets 40*333d2b36SAndroid Build Coastguard Worker} 41*333d2b36SAndroid Build Coastguard Worker 42*333d2b36SAndroid Build Coastguard Workervar ( 43*333d2b36SAndroid Build Coastguard Worker bootImageConfigKey = android.NewOnceKey("bootImageConfig") 44*333d2b36SAndroid Build Coastguard Worker bootImageConfigRawKey = android.NewOnceKey("bootImageConfigRaw") 45*333d2b36SAndroid Build Coastguard Worker frameworkBootImageName = "boot" 46*333d2b36SAndroid Build Coastguard Worker mainlineBootImageName = "mainline" 47*333d2b36SAndroid Build Coastguard Worker bootImageStem = "boot" 48*333d2b36SAndroid Build Coastguard Worker ProfileInstallPathInApex = "etc/boot-image.prof" 49*333d2b36SAndroid Build Coastguard Worker) 50*333d2b36SAndroid Build Coastguard Worker 51*333d2b36SAndroid Build Coastguard Worker// getImageNames returns an ordered list of image names. The order doesn't matter but needs to be 52*333d2b36SAndroid Build Coastguard Worker// deterministic. The names listed here must match the map keys returned by genBootImageConfigs. 53*333d2b36SAndroid Build Coastguard Workerfunc getImageNames() []string { 54*333d2b36SAndroid Build Coastguard Worker return []string{"art", "boot", "mainline"} 55*333d2b36SAndroid Build Coastguard Worker} 56*333d2b36SAndroid Build Coastguard Worker 57*333d2b36SAndroid Build Coastguard Workerfunc genBootImageConfigRaw(ctx android.PathContext) map[string]*bootImageConfig { 58*333d2b36SAndroid Build Coastguard Worker return ctx.Config().Once(bootImageConfigRawKey, func() interface{} { 59*333d2b36SAndroid Build Coastguard Worker global := dexpreopt.GetGlobalConfig(ctx) 60*333d2b36SAndroid Build Coastguard Worker 61*333d2b36SAndroid Build Coastguard Worker artBootImageName := "art" // Keep this local to avoid accidental references. 62*333d2b36SAndroid Build Coastguard Worker frameworkModules := global.BootJars // This includes `global.ArtApexJars`. 63*333d2b36SAndroid Build Coastguard Worker mainlineBcpModules := global.ApexBootJars 64*333d2b36SAndroid Build Coastguard Worker frameworkSubdir := "system/framework" 65*333d2b36SAndroid Build Coastguard Worker 66*333d2b36SAndroid Build Coastguard Worker profileImports := []string{"com.android.art"} 67*333d2b36SAndroid Build Coastguard Worker 68*333d2b36SAndroid Build Coastguard Worker // ART boot image for testing only. Do not rely on it to make any build-time decision. 69*333d2b36SAndroid Build Coastguard Worker artCfg := bootImageConfig{ 70*333d2b36SAndroid Build Coastguard Worker name: artBootImageName, 71*333d2b36SAndroid Build Coastguard Worker enabledIfExists: "art-bootclasspath-fragment", 72*333d2b36SAndroid Build Coastguard Worker stem: bootImageStem, 73*333d2b36SAndroid Build Coastguard Worker installDir: "apex/art_boot_images/javalib", 74*333d2b36SAndroid Build Coastguard Worker modules: global.TestOnlyArtBootImageJars, 75*333d2b36SAndroid Build Coastguard Worker preloadedClassesFile: "art/build/boot/preloaded-classes", 76*333d2b36SAndroid Build Coastguard Worker compilerFilter: "speed-profile", 77*333d2b36SAndroid Build Coastguard Worker singleImage: false, 78*333d2b36SAndroid Build Coastguard Worker profileImports: profileImports, 79*333d2b36SAndroid Build Coastguard Worker } 80*333d2b36SAndroid Build Coastguard Worker 81*333d2b36SAndroid Build Coastguard Worker // Framework config for the boot image extension. 82*333d2b36SAndroid Build Coastguard Worker // It includes framework libraries and depends on the ART config. 83*333d2b36SAndroid Build Coastguard Worker frameworkCfg := bootImageConfig{ 84*333d2b36SAndroid Build Coastguard Worker name: frameworkBootImageName, 85*333d2b36SAndroid Build Coastguard Worker enabledIfExists: "platform-bootclasspath", 86*333d2b36SAndroid Build Coastguard Worker stem: bootImageStem, 87*333d2b36SAndroid Build Coastguard Worker installDir: frameworkSubdir, 88*333d2b36SAndroid Build Coastguard Worker modules: frameworkModules, 89*333d2b36SAndroid Build Coastguard Worker preloadedClassesFile: "frameworks/base/config/preloaded-classes", 90*333d2b36SAndroid Build Coastguard Worker compilerFilter: "speed-profile", 91*333d2b36SAndroid Build Coastguard Worker singleImage: false, 92*333d2b36SAndroid Build Coastguard Worker profileImports: profileImports, 93*333d2b36SAndroid Build Coastguard Worker } 94*333d2b36SAndroid Build Coastguard Worker 95*333d2b36SAndroid Build Coastguard Worker mainlineCfg := bootImageConfig{ 96*333d2b36SAndroid Build Coastguard Worker extends: &frameworkCfg, 97*333d2b36SAndroid Build Coastguard Worker name: mainlineBootImageName, 98*333d2b36SAndroid Build Coastguard Worker enabledIfExists: "platform-bootclasspath", 99*333d2b36SAndroid Build Coastguard Worker stem: bootImageStem, 100*333d2b36SAndroid Build Coastguard Worker installDir: frameworkSubdir, 101*333d2b36SAndroid Build Coastguard Worker modules: mainlineBcpModules, 102*333d2b36SAndroid Build Coastguard Worker compilerFilter: "verify", 103*333d2b36SAndroid Build Coastguard Worker singleImage: true, 104*333d2b36SAndroid Build Coastguard Worker } 105*333d2b36SAndroid Build Coastguard Worker 106*333d2b36SAndroid Build Coastguard Worker return map[string]*bootImageConfig{ 107*333d2b36SAndroid Build Coastguard Worker artBootImageName: &artCfg, 108*333d2b36SAndroid Build Coastguard Worker frameworkBootImageName: &frameworkCfg, 109*333d2b36SAndroid Build Coastguard Worker mainlineBootImageName: &mainlineCfg, 110*333d2b36SAndroid Build Coastguard Worker } 111*333d2b36SAndroid Build Coastguard Worker }).(map[string]*bootImageConfig) 112*333d2b36SAndroid Build Coastguard Worker} 113*333d2b36SAndroid Build Coastguard Worker 114*333d2b36SAndroid Build Coastguard Worker// Construct the global boot image configs. 115*333d2b36SAndroid Build Coastguard Workerfunc genBootImageConfigs(ctx android.PathContext) map[string]*bootImageConfig { 116*333d2b36SAndroid Build Coastguard Worker return ctx.Config().Once(bootImageConfigKey, func() interface{} { 117*333d2b36SAndroid Build Coastguard Worker targets := dexpreoptTargets(ctx) 118*333d2b36SAndroid Build Coastguard Worker deviceDir := android.PathForOutput(ctx, dexpreopt.GetDexpreoptDirName(ctx)) 119*333d2b36SAndroid Build Coastguard Worker 120*333d2b36SAndroid Build Coastguard Worker configs := genBootImageConfigRaw(ctx) 121*333d2b36SAndroid Build Coastguard Worker 122*333d2b36SAndroid Build Coastguard Worker for _, c := range configs { 123*333d2b36SAndroid Build Coastguard Worker c.dir = deviceDir.Join(ctx, "dex_"+c.name+"jars") 124*333d2b36SAndroid Build Coastguard Worker c.symbolsDir = deviceDir.Join(ctx, "dex_"+c.name+"jars_unstripped") 125*333d2b36SAndroid Build Coastguard Worker 126*333d2b36SAndroid Build Coastguard Worker // expands to <stem>.art for primary image and <stem>-<1st module>.art for extension 127*333d2b36SAndroid Build Coastguard Worker imageName := c.firstModuleNameOrStem(ctx) + ".art" 128*333d2b36SAndroid Build Coastguard Worker 129*333d2b36SAndroid Build Coastguard Worker // The path to bootclasspath dex files needs to be known at module 130*333d2b36SAndroid Build Coastguard Worker // GenerateAndroidBuildAction time, before the bootclasspath modules have been compiled. 131*333d2b36SAndroid Build Coastguard Worker // Set up known paths for them, the singleton rules will copy them there. 132*333d2b36SAndroid Build Coastguard Worker // TODO(b/143682396): use module dependencies instead 133*333d2b36SAndroid Build Coastguard Worker inputDir := deviceDir.Join(ctx, "dex_"+c.name+"jars_input") 134*333d2b36SAndroid Build Coastguard Worker c.dexPaths = c.modules.BuildPaths(ctx, inputDir) 135*333d2b36SAndroid Build Coastguard Worker c.dexPathsByModule = c.modules.BuildPathsByModule(ctx, inputDir) 136*333d2b36SAndroid Build Coastguard Worker c.dexPathsDeps = c.dexPaths 137*333d2b36SAndroid Build Coastguard Worker 138*333d2b36SAndroid Build Coastguard Worker // Create target-specific variants. 139*333d2b36SAndroid Build Coastguard Worker for _, target := range targets { 140*333d2b36SAndroid Build Coastguard Worker arch := target.Arch.ArchType 141*333d2b36SAndroid Build Coastguard Worker imageDir := c.dir.Join(ctx, target.Os.String(), c.installDir, arch.String()) 142*333d2b36SAndroid Build Coastguard Worker variant := &bootImageVariant{ 143*333d2b36SAndroid Build Coastguard Worker bootImageConfig: c, 144*333d2b36SAndroid Build Coastguard Worker target: target, 145*333d2b36SAndroid Build Coastguard Worker imagePathOnHost: imageDir.Join(ctx, imageName), 146*333d2b36SAndroid Build Coastguard Worker imagePathOnDevice: filepath.Join("/", c.installDir, arch.String(), imageName), 147*333d2b36SAndroid Build Coastguard Worker imagesDeps: c.moduleFiles(ctx, imageDir, ".art", ".oat", ".vdex"), 148*333d2b36SAndroid Build Coastguard Worker dexLocations: c.modules.DevicePaths(ctx.Config(), target.Os), 149*333d2b36SAndroid Build Coastguard Worker } 150*333d2b36SAndroid Build Coastguard Worker variant.dexLocationsDeps = variant.dexLocations 151*333d2b36SAndroid Build Coastguard Worker c.variants = append(c.variants, variant) 152*333d2b36SAndroid Build Coastguard Worker } 153*333d2b36SAndroid Build Coastguard Worker 154*333d2b36SAndroid Build Coastguard Worker c.zip = c.dir.Join(ctx, c.name+".zip") 155*333d2b36SAndroid Build Coastguard Worker } 156*333d2b36SAndroid Build Coastguard Worker 157*333d2b36SAndroid Build Coastguard Worker visited := make(map[string]bool) 158*333d2b36SAndroid Build Coastguard Worker for _, c := range configs { 159*333d2b36SAndroid Build Coastguard Worker calculateDepsRecursive(c, targets, visited) 160*333d2b36SAndroid Build Coastguard Worker } 161*333d2b36SAndroid Build Coastguard Worker 162*333d2b36SAndroid Build Coastguard Worker return configs 163*333d2b36SAndroid Build Coastguard Worker }).(map[string]*bootImageConfig) 164*333d2b36SAndroid Build Coastguard Worker} 165*333d2b36SAndroid Build Coastguard Worker 166*333d2b36SAndroid Build Coastguard Worker// calculateDepsRecursive calculates the dependencies of the given boot image config and all its 167*333d2b36SAndroid Build Coastguard Worker// ancestors, if they are not visited. 168*333d2b36SAndroid Build Coastguard Worker// The boot images are supposed to form a tree, where the root is the primary boot image. We do not 169*333d2b36SAndroid Build Coastguard Worker// expect loops (e.g., A extends B, B extends C, C extends A), and we let them crash soong with a 170*333d2b36SAndroid Build Coastguard Worker// stack overflow. 171*333d2b36SAndroid Build Coastguard Worker// Note that a boot image config only has a pointer to the parent, not to children. Therefore, we 172*333d2b36SAndroid Build Coastguard Worker// first go up through the parent chain, and then go back down to visit every code along the path. 173*333d2b36SAndroid Build Coastguard Worker// `visited` is a map where a key is a boot image name and the value indicates whether the boot 174*333d2b36SAndroid Build Coastguard Worker// image config is visited. The boot image names are guaranteed to be unique because they come from 175*333d2b36SAndroid Build Coastguard Worker// `genBootImageConfigRaw` above, which also returns a map and would fail in the first place if the 176*333d2b36SAndroid Build Coastguard Worker// names were not unique. 177*333d2b36SAndroid Build Coastguard Workerfunc calculateDepsRecursive(c *bootImageConfig, targets []android.Target, visited map[string]bool) { 178*333d2b36SAndroid Build Coastguard Worker if c.extends == nil || visited[c.name] { 179*333d2b36SAndroid Build Coastguard Worker return 180*333d2b36SAndroid Build Coastguard Worker } 181*333d2b36SAndroid Build Coastguard Worker if c.extends.extends != nil { 182*333d2b36SAndroid Build Coastguard Worker calculateDepsRecursive(c.extends, targets, visited) 183*333d2b36SAndroid Build Coastguard Worker } 184*333d2b36SAndroid Build Coastguard Worker visited[c.name] = true 185*333d2b36SAndroid Build Coastguard Worker c.dexPathsDeps = android.Concat(c.extends.dexPathsDeps, c.dexPathsDeps) 186*333d2b36SAndroid Build Coastguard Worker for i := range targets { 187*333d2b36SAndroid Build Coastguard Worker c.variants[i].baseImages = android.Concat(c.extends.variants[i].baseImages, android.OutputPaths{c.extends.variants[i].imagePathOnHost}) 188*333d2b36SAndroid Build Coastguard Worker c.variants[i].baseImagesDeps = android.Concat(c.extends.variants[i].baseImagesDeps, c.extends.variants[i].imagesDeps.Paths()) 189*333d2b36SAndroid Build Coastguard Worker c.variants[i].dexLocationsDeps = android.Concat(c.extends.variants[i].dexLocationsDeps, c.variants[i].dexLocationsDeps) 190*333d2b36SAndroid Build Coastguard Worker } 191*333d2b36SAndroid Build Coastguard Worker} 192*333d2b36SAndroid Build Coastguard Worker 193*333d2b36SAndroid Build Coastguard Workerfunc defaultBootImageConfig(ctx android.PathContext) *bootImageConfig { 194*333d2b36SAndroid Build Coastguard Worker return genBootImageConfigs(ctx)[frameworkBootImageName] 195*333d2b36SAndroid Build Coastguard Worker} 196*333d2b36SAndroid Build Coastguard Worker 197*333d2b36SAndroid Build Coastguard Workerfunc mainlineBootImageConfig(ctx android.PathContext) *bootImageConfig { 198*333d2b36SAndroid Build Coastguard Worker return genBootImageConfigs(ctx)[mainlineBootImageName] 199*333d2b36SAndroid Build Coastguard Worker} 200*333d2b36SAndroid Build Coastguard Worker 201*333d2b36SAndroid Build Coastguard Worker// isProfileProviderApex returns true if this apex provides a boot image profile. 202*333d2b36SAndroid Build Coastguard Workerfunc isProfileProviderApex(ctx android.PathContext, apexName string) bool { 203*333d2b36SAndroid Build Coastguard Worker for _, config := range genBootImageConfigs(ctx) { 204*333d2b36SAndroid Build Coastguard Worker for _, profileImport := range config.profileImports { 205*333d2b36SAndroid Build Coastguard Worker if profileImport == apexName { 206*333d2b36SAndroid Build Coastguard Worker return true 207*333d2b36SAndroid Build Coastguard Worker } 208*333d2b36SAndroid Build Coastguard Worker } 209*333d2b36SAndroid Build Coastguard Worker } 210*333d2b36SAndroid Build Coastguard Worker return false 211*333d2b36SAndroid Build Coastguard Worker} 212*333d2b36SAndroid Build Coastguard Worker 213*333d2b36SAndroid Build Coastguard Worker// Returns a list of paths and a list of locations for the boot jars used in dexpreopt (to be 214*333d2b36SAndroid Build Coastguard Worker// passed in -Xbootclasspath and -Xbootclasspath-locations arguments for dex2oat). 215*333d2b36SAndroid Build Coastguard Workerfunc bcpForDexpreopt(ctx android.PathContext, withUpdatable bool) (android.WritablePaths, []string) { 216*333d2b36SAndroid Build Coastguard Worker bootImage := defaultBootImageConfig(ctx) 217*333d2b36SAndroid Build Coastguard Worker if withUpdatable { 218*333d2b36SAndroid Build Coastguard Worker bootImage = mainlineBootImageConfig(ctx) 219*333d2b36SAndroid Build Coastguard Worker } 220*333d2b36SAndroid Build Coastguard Worker 221*333d2b36SAndroid Build Coastguard Worker dexPaths := bootImage.dexPathsDeps 222*333d2b36SAndroid Build Coastguard Worker // The dex locations for all Android variants are identical. 223*333d2b36SAndroid Build Coastguard Worker dexLocations := bootImage.getAnyAndroidVariant().dexLocationsDeps 224*333d2b36SAndroid Build Coastguard Worker 225*333d2b36SAndroid Build Coastguard Worker return dexPaths, dexLocations 226*333d2b36SAndroid Build Coastguard Worker} 227*333d2b36SAndroid Build Coastguard Worker 228*333d2b36SAndroid Build Coastguard Workervar defaultBootclasspathKey = android.NewOnceKey("defaultBootclasspath") 229*333d2b36SAndroid Build Coastguard Worker 230*333d2b36SAndroid Build Coastguard Workerfunc init() { 231*333d2b36SAndroid Build Coastguard Worker android.RegisterMakeVarsProvider(pctx, dexpreoptConfigMakevars) 232*333d2b36SAndroid Build Coastguard Worker} 233*333d2b36SAndroid Build Coastguard Worker 234*333d2b36SAndroid Build Coastguard Workerfunc dexpreoptConfigMakevars(ctx android.MakeVarsContext) { 235*333d2b36SAndroid Build Coastguard Worker ctx.Strict("DEXPREOPT_BOOT_JARS_MODULES", strings.Join(defaultBootImageConfig(ctx).modules.CopyOfApexJarPairs(), ":")) 236*333d2b36SAndroid Build Coastguard Worker} 237