• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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