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