blob: 78215f05a403020dc488a96d4de6b71c16602d90 [file] [log] [blame]
Paul Duffin3451e162021-01-20 15:16:56 +00001// Copyright (C) 2021 The Android Open Source Project
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 (
Paul Duffina1d60252021-01-21 18:13:43 +000018 "fmt"
Paul Duffin3451e162021-01-20 15:16:56 +000019 "strings"
20
21 "android/soong/android"
Paul Duffina1d60252021-01-21 18:13:43 +000022 "android/soong/dexpreopt"
Paul Duffinc7ef9892021-03-23 23:21:59 +000023 "github.com/google/blueprint/proptools"
Martin Stjernholmb79c7f12021-03-17 00:26:25 +000024
Paul Duffin3451e162021-01-20 15:16:56 +000025 "github.com/google/blueprint"
26)
27
28func init() {
29 RegisterBootImageBuildComponents(android.InitRegistrationContext)
Paul Duffinf7f65da2021-03-10 15:00:46 +000030
Paul Duffin4b64ba02021-03-29 11:02:53 +010031 // TODO(b/177892522): Remove after has been replaced by bootclasspath_fragments
Paul Duffinf7f65da2021-03-10 15:00:46 +000032 android.RegisterSdkMemberType(&bootImageMemberType{
33 SdkMemberTypeBase: android.SdkMemberTypeBase{
34 PropertyName: "boot_images",
35 SupportsSdk: true,
36 },
37 })
Paul Duffin4b64ba02021-03-29 11:02:53 +010038
39 android.RegisterSdkMemberType(&bootImageMemberType{
40 SdkMemberTypeBase: android.SdkMemberTypeBase{
41 PropertyName: "bootclasspath_fragments",
42 SupportsSdk: true,
43 },
44 })
Paul Duffin3451e162021-01-20 15:16:56 +000045}
46
47func RegisterBootImageBuildComponents(ctx android.RegistrationContext) {
Paul Duffin4b64ba02021-03-29 11:02:53 +010048 // TODO(b/177892522): Remove after has been replaced by bootclasspath_fragment
Paul Duffin3451e162021-01-20 15:16:56 +000049 ctx.RegisterModuleType("boot_image", bootImageFactory)
Paul Duffinf7f65da2021-03-10 15:00:46 +000050 ctx.RegisterModuleType("prebuilt_boot_image", prebuiltBootImageFactory)
Paul Duffin4b64ba02021-03-29 11:02:53 +010051
52 ctx.RegisterModuleType("bootclasspath_fragment", bootImageFactory)
53 ctx.RegisterModuleType("prebuilt_bootclasspath_fragment", prebuiltBootImageFactory)
Paul Duffin3451e162021-01-20 15:16:56 +000054}
55
Paul Duffinc7ef9892021-03-23 23:21:59 +000056type bootImageContentDependencyTag struct {
57 blueprint.BaseDependencyTag
58}
59
60// Avoid having to make boot image content visible to the boot image.
61//
62// This is a temporary workaround to make it easier to migrate to boot image modules with proper
63// dependencies.
64// TODO(b/177892522): Remove this and add needed visibility.
65func (b bootImageContentDependencyTag) ExcludeFromVisibilityEnforcement() {
66}
67
68// The tag used for the dependency between the boot image module and its contents.
69var bootImageContentDepTag = bootImageContentDependencyTag{}
70
71var _ android.ExcludeFromVisibilityEnforcementTag = bootImageContentDepTag
72
Paul Duffin4d101b62021-03-24 15:42:20 +000073func IsbootImageContentDepTag(tag blueprint.DependencyTag) bool {
74 return tag == bootImageContentDepTag
75}
76
Paul Duffin3451e162021-01-20 15:16:56 +000077type bootImageProperties struct {
78 // The name of the image this represents.
79 //
Paul Duffin82886d62021-03-24 01:34:57 +000080 // If specified then it must be one of "art" or "boot".
Paul Duffin64be7bb2021-03-23 23:06:38 +000081 Image_name *string
Paul Duffinc7ef9892021-03-23 23:21:59 +000082
83 // The contents of this boot image, could be either java_library, java_sdk_library, or boot_image.
84 //
85 // The order of this list matters as it is the order that is used in the bootclasspath.
Paul Duffin82886d62021-03-24 01:34:57 +000086 Contents []string
Paul Duffin9b381ef2021-04-08 23:01:37 +010087
88 Hidden_api HiddenAPIFlagFileProperties
Paul Duffin3451e162021-01-20 15:16:56 +000089}
90
91type BootImageModule struct {
92 android.ModuleBase
Paul Duffina1d60252021-01-21 18:13:43 +000093 android.ApexModuleBase
Paul Duffinf7f65da2021-03-10 15:00:46 +000094 android.SdkBase
Paul Duffin3451e162021-01-20 15:16:56 +000095 properties bootImageProperties
96}
97
98func bootImageFactory() android.Module {
99 m := &BootImageModule{}
100 m.AddProperties(&m.properties)
Paul Duffina1d60252021-01-21 18:13:43 +0000101 android.InitApexModule(m)
Paul Duffinf7f65da2021-03-10 15:00:46 +0000102 android.InitSdkAwareModule(m)
Martin Stjernholmb79c7f12021-03-17 00:26:25 +0000103 android.InitAndroidArchModule(m, android.HostAndDeviceSupported, android.MultilibCommon)
Paul Duffinc7ef9892021-03-23 23:21:59 +0000104
105 // Perform some consistency checking to ensure that the configuration is correct.
106 android.AddLoadHook(m, func(ctx android.LoadHookContext) {
107 bootImageConsistencyCheck(ctx, m)
108 })
Paul Duffin3451e162021-01-20 15:16:56 +0000109 return m
110}
111
Paul Duffinc7ef9892021-03-23 23:21:59 +0000112func bootImageConsistencyCheck(ctx android.EarlyModuleContext, m *BootImageModule) {
Paul Duffin82886d62021-03-24 01:34:57 +0000113 contents := m.properties.Contents
114 if m.properties.Image_name == nil && len(contents) == 0 {
115 ctx.ModuleErrorf(`neither of the "image_name" and "contents" properties have been supplied, please supply exactly one`)
116 }
117 if m.properties.Image_name != nil && len(contents) != 0 {
118 ctx.ModuleErrorf(`both of the "image_name" and "contents" properties have been supplied, please supply exactly one`)
119 }
Paul Duffinc7ef9892021-03-23 23:21:59 +0000120 imageName := proptools.String(m.properties.Image_name)
121 if imageName == "art" {
122 // Get the configuration for the art apex jars. Do not use getImageConfig(ctx) here as this is
123 // too early in the Soong processing for that to work.
124 global := dexpreopt.GetGlobalConfig(ctx)
125 modules := global.ArtApexJars
126
127 // Make sure that the apex specified in the configuration is consistent and is one for which
128 // this boot image is available.
129 jars := []string{}
130 commonApex := ""
131 for i := 0; i < modules.Len(); i++ {
132 apex := modules.Apex(i)
133 jar := modules.Jar(i)
134 if apex == "platform" {
135 ctx.ModuleErrorf("ArtApexJars is invalid as it requests a platform variant of %q", jar)
136 continue
137 }
138 if !m.AvailableFor(apex) {
139 ctx.ModuleErrorf("incompatible with ArtApexJars which expects this to be in apex %q but this is only in apexes %q",
140 apex, m.ApexAvailable())
141 continue
142 }
143 if commonApex == "" {
144 commonApex = apex
145 } else if commonApex != apex {
146 ctx.ModuleErrorf("ArtApexJars configuration is inconsistent, expected all jars to be in the same apex but it specifies apex %q and %q",
147 commonApex, apex)
148 }
149 jars = append(jars, jar)
150 }
151
152 // Store the jars in the Contents property so that they can be used to add dependencies.
153 m.properties.Contents = jars
154 }
155}
156
Paul Duffin3451e162021-01-20 15:16:56 +0000157var BootImageInfoProvider = blueprint.NewProvider(BootImageInfo{})
158
159type BootImageInfo struct {
160 // The image config, internal to this module (and the dex_bootjars singleton).
Paul Duffina1d60252021-01-21 18:13:43 +0000161 //
162 // Will be nil if the BootImageInfo has not been provided for a specific module. That can occur
163 // when SkipDexpreoptBootJars(ctx) returns true.
Paul Duffin3451e162021-01-20 15:16:56 +0000164 imageConfig *bootImageConfig
165}
166
167func (i BootImageInfo) Modules() android.ConfiguredJarList {
168 return i.imageConfig.modules
169}
170
Paul Duffina1d60252021-01-21 18:13:43 +0000171// Get a map from ArchType to the associated boot image's contents for Android.
172//
173// Extension boot images only return their own files, not the files of the boot images they extend.
174func (i BootImageInfo) AndroidBootImageFilesByArchType() map[android.ArchType]android.OutputPaths {
175 files := map[android.ArchType]android.OutputPaths{}
176 if i.imageConfig != nil {
177 for _, variant := range i.imageConfig.variants {
178 // We also generate boot images for host (for testing), but we don't need those in the apex.
179 // TODO(b/177892522) - consider changing this to check Os.OsClass = android.Device
180 if variant.target.Os == android.Android {
181 files[variant.target.Arch.ArchType] = variant.imagesDeps
182 }
183 }
184 }
185 return files
186}
187
188func (b *BootImageModule) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
189 tag := ctx.OtherModuleDependencyTag(dep)
Paul Duffinc7ef9892021-03-23 23:21:59 +0000190 if tag == bootImageContentDepTag {
Paul Duffin4d101b62021-03-24 15:42:20 +0000191 // Boot image contents are automatically added to apex.
192 return true
Paul Duffinc7ef9892021-03-23 23:21:59 +0000193 }
Bob Badour07065cd2021-02-05 19:59:11 -0800194 if android.IsMetaDependencyTag(tag) {
195 // Cross-cutting metadata dependencies are metadata.
196 return false
197 }
Paul Duffina1d60252021-01-21 18:13:43 +0000198 panic(fmt.Errorf("boot_image module %q should not have a dependency on %q via tag %s", b, dep, android.PrettyPrintTag(tag)))
199}
200
201func (b *BootImageModule) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion android.ApiLevel) error {
202 return nil
203}
204
205func (b *BootImageModule) DepsMutator(ctx android.BottomUpMutatorContext) {
Paul Duffinc7ef9892021-03-23 23:21:59 +0000206 ctx.AddDependency(ctx.Module(), bootImageContentDepTag, b.properties.Contents...)
207
Paul Duffina1d60252021-01-21 18:13:43 +0000208 if SkipDexpreoptBootJars(ctx) {
209 return
210 }
211
212 // Add a dependency onto the dex2oat tool which is needed for creating the boot image. The
213 // path is retrieved from the dependency by GetGlobalSoongConfig(ctx).
214 dexpreopt.RegisterToolDeps(ctx)
215}
216
Paul Duffin3451e162021-01-20 15:16:56 +0000217func (b *BootImageModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
Paul Duffin9b381ef2021-04-08 23:01:37 +0100218 // Perform hidden API processing.
219 b.generateHiddenAPIBuildActions(ctx)
220
Paul Duffin3451e162021-01-20 15:16:56 +0000221 // Nothing to do if skipping the dexpreopt of boot image jars.
222 if SkipDexpreoptBootJars(ctx) {
223 return
224 }
225
Paul Duffina1d60252021-01-21 18:13:43 +0000226 // Force the GlobalSoongConfig to be created and cached for use by the dex_bootjars
227 // GenerateSingletonBuildActions method as it cannot create it for itself.
228 dexpreopt.GetGlobalSoongConfig(ctx)
229
Paul Duffin64be7bb2021-03-23 23:06:38 +0000230 imageConfig := b.getImageConfig(ctx)
Paul Duffin3451e162021-01-20 15:16:56 +0000231 if imageConfig == nil {
Paul Duffin3451e162021-01-20 15:16:56 +0000232 return
233 }
234
235 // Construct the boot image info from the config.
236 info := BootImageInfo{imageConfig: imageConfig}
237
238 // Make it available for other modules.
239 ctx.SetProvider(BootImageInfoProvider, info)
240}
Paul Duffinf7f65da2021-03-10 15:00:46 +0000241
Paul Duffin64be7bb2021-03-23 23:06:38 +0000242func (b *BootImageModule) getImageConfig(ctx android.EarlyModuleContext) *bootImageConfig {
243 // Get a map of the image configs that are supported.
244 imageConfigs := genBootImageConfigs(ctx)
245
246 // Retrieve the config for this image.
247 imageNamePtr := b.properties.Image_name
248 if imageNamePtr == nil {
249 return nil
250 }
251
252 imageName := *imageNamePtr
253 imageConfig := imageConfigs[imageName]
254 if imageConfig == nil {
255 ctx.PropertyErrorf("image_name", "Unknown image name %q, expected one of %s", imageName, strings.Join(android.SortedStringKeys(imageConfigs), ", "))
256 return nil
257 }
258 return imageConfig
259}
260
Paul Duffin9b381ef2021-04-08 23:01:37 +0100261// generateHiddenAPIBuildActions generates all the hidden API related build rules.
262func (b *BootImageModule) generateHiddenAPIBuildActions(ctx android.ModuleContext) {
263 // Resolve the properties to paths.
264 flagFileInfo := b.properties.Hidden_api.hiddenAPIFlagFileInfo(ctx)
265
266 // Store the information for use by platform_bootclasspath.
267 ctx.SetProvider(hiddenAPIFlagFileInfoProvider, flagFileInfo)
268}
269
Paul Duffinf7f65da2021-03-10 15:00:46 +0000270type bootImageMemberType struct {
271 android.SdkMemberTypeBase
272}
273
274func (b *bootImageMemberType) AddDependencies(mctx android.BottomUpMutatorContext, dependencyTag blueprint.DependencyTag, names []string) {
275 mctx.AddVariationDependencies(nil, dependencyTag, names...)
276}
277
278func (b *bootImageMemberType) IsInstance(module android.Module) bool {
279 _, ok := module.(*BootImageModule)
280 return ok
281}
282
283func (b *bootImageMemberType) AddPrebuiltModule(ctx android.SdkMemberContext, member android.SdkMember) android.BpModule {
Paul Duffin4b64ba02021-03-29 11:02:53 +0100284 if b.PropertyName == "boot_images" {
285 return ctx.SnapshotBuilder().AddPrebuiltModule(member, "prebuilt_boot_image")
286 } else {
287 return ctx.SnapshotBuilder().AddPrebuiltModule(member, "prebuilt_bootclasspath_fragment")
288 }
Paul Duffinf7f65da2021-03-10 15:00:46 +0000289}
290
291func (b *bootImageMemberType) CreateVariantPropertiesStruct() android.SdkMemberProperties {
292 return &bootImageSdkMemberProperties{}
293}
294
295type bootImageSdkMemberProperties struct {
296 android.SdkMemberPropertiesBase
297
Paul Duffin64be7bb2021-03-23 23:06:38 +0000298 Image_name *string
Paul Duffinf7f65da2021-03-10 15:00:46 +0000299}
300
301func (b *bootImageSdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) {
302 module := variant.(*BootImageModule)
303
304 b.Image_name = module.properties.Image_name
305}
306
307func (b *bootImageSdkMemberProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) {
Paul Duffin64be7bb2021-03-23 23:06:38 +0000308 if b.Image_name != nil {
309 propertySet.AddProperty("image_name", *b.Image_name)
Paul Duffinf7f65da2021-03-10 15:00:46 +0000310 }
311}
312
313var _ android.SdkMemberType = (*bootImageMemberType)(nil)
314
315// A prebuilt version of the boot image module.
316//
317// At the moment this is basically just a boot image module that can be used as a prebuilt.
318// Eventually as more functionality is migrated into the boot image module from the singleton then
319// this will diverge.
320type prebuiltBootImageModule struct {
321 BootImageModule
322 prebuilt android.Prebuilt
323}
324
325func (module *prebuiltBootImageModule) Prebuilt() *android.Prebuilt {
326 return &module.prebuilt
327}
328
329func (module *prebuiltBootImageModule) Name() string {
330 return module.prebuilt.Name(module.ModuleBase.Name())
331}
332
333func prebuiltBootImageFactory() android.Module {
334 m := &prebuiltBootImageModule{}
335 m.AddProperties(&m.properties)
Paul Duffinf7f65da2021-03-10 15:00:46 +0000336 // This doesn't actually have any prebuilt files of its own so pass a placeholder for the srcs
337 // array.
338 android.InitPrebuiltModule(m, &[]string{"placeholder"})
339 android.InitApexModule(m)
340 android.InitSdkAwareModule(m)
Martin Stjernholmb79c7f12021-03-17 00:26:25 +0000341 android.InitAndroidArchModule(m, android.HostAndDeviceSupported, android.MultilibCommon)
Paul Duffinc7ef9892021-03-23 23:21:59 +0000342
343 // Perform some consistency checking to ensure that the configuration is correct.
344 android.AddLoadHook(m, func(ctx android.LoadHookContext) {
345 bootImageConsistencyCheck(ctx, &m.BootImageModule)
346 })
Paul Duffinf7f65da2021-03-10 15:00:46 +0000347 return m
348}