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 "path/filepath" 19 "strings" 20 21 "android/soong/android" 22 "android/soong/dexpreopt" 23) 24 25// dexpreoptTargets returns the list of targets that are relevant to dexpreopting, which excludes architectures 26// supported through native bridge. 27func dexpreoptTargets(ctx android.PathContext) []android.Target { 28 var targets []android.Target 29 for _, target := range ctx.Config().Targets[android.Android] { 30 if target.NativeBridge == android.NativeBridgeDisabled { 31 targets = append(targets, target) 32 } 33 } 34 // We may also need the images on host in order to run host-based tests. 35 for _, target := range ctx.Config().Targets[ctx.Config().BuildOS] { 36 targets = append(targets, target) 37 } 38 39 return targets 40} 41 42var ( 43 bootImageConfigKey = android.NewOnceKey("bootImageConfig") 44 bootImageConfigRawKey = android.NewOnceKey("bootImageConfigRaw") 45 artBootImageName = "art" 46 frameworkBootImageName = "boot" 47) 48 49func genBootImageConfigRaw(ctx android.PathContext) map[string]*bootImageConfig { 50 return ctx.Config().Once(bootImageConfigRawKey, func() interface{} { 51 global := dexpreopt.GetGlobalConfig(ctx) 52 53 artModules := global.ArtApexJars 54 frameworkModules := global.BootJars.RemoveList(artModules) 55 56 // ART config for the primary boot image in the ART apex. 57 // It includes the Core Libraries. 58 artCfg := bootImageConfig{ 59 name: artBootImageName, 60 stem: "boot", 61 installDirOnHost: "apex/art_boot_images/javalib", 62 installDirOnDevice: "system/framework", 63 profileInstallPathInApex: "etc/boot-image.prof", 64 modules: artModules, 65 preloadedClassesFile: "art/build/boot/preloaded-classes", 66 } 67 68 // Framework config for the boot image extension. 69 // It includes framework libraries and depends on the ART config. 70 frameworkSubdir := "system/framework" 71 frameworkCfg := bootImageConfig{ 72 extends: &artCfg, 73 name: frameworkBootImageName, 74 stem: "boot", 75 installDirOnHost: frameworkSubdir, 76 installDirOnDevice: frameworkSubdir, 77 modules: frameworkModules, 78 preloadedClassesFile: "frameworks/base/config/preloaded-classes", 79 } 80 81 return map[string]*bootImageConfig{ 82 artBootImageName: &artCfg, 83 frameworkBootImageName: &frameworkCfg, 84 } 85 }).(map[string]*bootImageConfig) 86} 87 88// Construct the global boot image configs. 89func genBootImageConfigs(ctx android.PathContext) map[string]*bootImageConfig { 90 return ctx.Config().Once(bootImageConfigKey, func() interface{} { 91 targets := dexpreoptTargets(ctx) 92 deviceDir := android.PathForOutput(ctx, ctx.Config().DeviceName()) 93 94 configs := genBootImageConfigRaw(ctx) 95 artCfg := configs[artBootImageName] 96 frameworkCfg := configs[frameworkBootImageName] 97 98 // common to all configs 99 for _, c := range configs { 100 c.dir = deviceDir.Join(ctx, "dex_"+c.name+"jars") 101 c.symbolsDir = deviceDir.Join(ctx, "dex_"+c.name+"jars_unstripped") 102 103 // expands to <stem>.art for primary image and <stem>-<1st module>.art for extension 104 imageName := c.firstModuleNameOrStem(ctx) + ".art" 105 106 // The path to bootclasspath dex files needs to be known at module 107 // GenerateAndroidBuildAction time, before the bootclasspath modules have been compiled. 108 // Set up known paths for them, the singleton rules will copy them there. 109 // TODO(b/143682396): use module dependencies instead 110 inputDir := deviceDir.Join(ctx, "dex_"+c.name+"jars_input") 111 c.dexPaths = c.modules.BuildPaths(ctx, inputDir) 112 c.dexPathsByModule = c.modules.BuildPathsByModule(ctx, inputDir) 113 c.dexPathsDeps = c.dexPaths 114 115 // Create target-specific variants. 116 for _, target := range targets { 117 arch := target.Arch.ArchType 118 imageDir := c.dir.Join(ctx, target.Os.String(), c.installDirOnHost, arch.String()) 119 variant := &bootImageVariant{ 120 bootImageConfig: c, 121 target: target, 122 imagePathOnHost: imageDir.Join(ctx, imageName), 123 imagePathOnDevice: filepath.Join("/", c.installDirOnDevice, arch.String(), imageName), 124 imagesDeps: c.moduleFiles(ctx, imageDir, ".art", ".oat", ".vdex"), 125 dexLocations: c.modules.DevicePaths(ctx.Config(), target.Os), 126 } 127 variant.dexLocationsDeps = variant.dexLocations 128 c.variants = append(c.variants, variant) 129 } 130 131 c.zip = c.dir.Join(ctx, c.name+".zip") 132 } 133 134 // specific to the framework config 135 frameworkCfg.dexPathsDeps = append(artCfg.dexPathsDeps, frameworkCfg.dexPathsDeps...) 136 for i := range targets { 137 frameworkCfg.variants[i].primaryImages = artCfg.variants[i].imagePathOnHost 138 frameworkCfg.variants[i].primaryImagesDeps = artCfg.variants[i].imagesDeps.Paths() 139 frameworkCfg.variants[i].dexLocationsDeps = append(artCfg.variants[i].dexLocations, frameworkCfg.variants[i].dexLocationsDeps...) 140 } 141 142 return configs 143 }).(map[string]*bootImageConfig) 144} 145 146func artBootImageConfig(ctx android.PathContext) *bootImageConfig { 147 return genBootImageConfigs(ctx)[artBootImageName] 148} 149 150func defaultBootImageConfig(ctx android.PathContext) *bootImageConfig { 151 return genBootImageConfigs(ctx)[frameworkBootImageName] 152} 153 154// Apex boot config allows to access build/install paths of apex boot jars without going 155// through the usual trouble of registering dependencies on those modules and extracting build paths 156// from those dependencies. 157type apexBootConfig struct { 158 // A list of apex boot jars. 159 modules android.ConfiguredJarList 160 161 // A list of predefined build paths to apex boot jars. They are configured very early, 162 // before the modules for these jars are processed and the actual paths are generated, and 163 // later on a singleton adds commands to copy actual jars to the predefined paths. 164 dexPaths android.WritablePaths 165 166 // Map from module name (without prebuilt_ prefix) to the predefined build path. 167 dexPathsByModule map[string]android.WritablePath 168 169 // A list of dex locations (a.k.a. on-device paths) to the boot jars. 170 dexLocations []string 171} 172 173var updatableBootConfigKey = android.NewOnceKey("apexBootConfig") 174 175// Returns apex boot config. 176func GetApexBootConfig(ctx android.PathContext) apexBootConfig { 177 return ctx.Config().Once(updatableBootConfigKey, func() interface{} { 178 apexBootJars := dexpreopt.GetGlobalConfig(ctx).ApexBootJars 179 180 dir := android.PathForOutput(ctx, ctx.Config().DeviceName(), "apex_bootjars") 181 dexPaths := apexBootJars.BuildPaths(ctx, dir) 182 dexPathsByModuleName := apexBootJars.BuildPathsByModule(ctx, dir) 183 184 dexLocations := apexBootJars.DevicePaths(ctx.Config(), android.Android) 185 186 return apexBootConfig{apexBootJars, dexPaths, dexPathsByModuleName, dexLocations} 187 }).(apexBootConfig) 188} 189 190// Returns a list of paths and a list of locations for the boot jars used in dexpreopt (to be 191// passed in -Xbootclasspath and -Xbootclasspath-locations arguments for dex2oat). 192func bcpForDexpreopt(ctx android.PathContext, withUpdatable bool) (android.WritablePaths, []string) { 193 // Non-updatable boot jars (they are used both in the boot image and in dexpreopt). 194 bootImage := defaultBootImageConfig(ctx) 195 dexPaths := bootImage.dexPathsDeps 196 // The dex locations for all Android variants are identical. 197 dexLocations := bootImage.getAnyAndroidVariant().dexLocationsDeps 198 199 if withUpdatable { 200 // Apex boot jars (they are used only in dexpreopt, but not in the boot image). 201 apexBootConfig := GetApexBootConfig(ctx) 202 dexPaths = append(dexPaths, apexBootConfig.dexPaths...) 203 dexLocations = append(dexLocations, apexBootConfig.dexLocations...) 204 } 205 206 return dexPaths, dexLocations 207} 208 209var defaultBootclasspathKey = android.NewOnceKey("defaultBootclasspath") 210 211var copyOf = android.CopyOf 212 213func init() { 214 android.RegisterMakeVarsProvider(pctx, dexpreoptConfigMakevars) 215} 216 217func dexpreoptConfigMakevars(ctx android.MakeVarsContext) { 218 ctx.Strict("DEXPREOPT_BOOT_JARS_MODULES", strings.Join(defaultBootImageConfig(ctx).modules.CopyOfApexJarPairs(), ":")) 219} 220