blob: 0c4797609450e232f887f97669b64de1ea49e09f [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 Duffin3451e162021-01-20 15:16:56 +000087}
88
89type BootImageModule struct {
90 android.ModuleBase
Paul Duffina1d60252021-01-21 18:13:43 +000091 android.ApexModuleBase
Paul Duffinf7f65da2021-03-10 15:00:46 +000092 android.SdkBase
Paul Duffin3451e162021-01-20 15:16:56 +000093 properties bootImageProperties
94}
95
96func bootImageFactory() android.Module {
97 m := &BootImageModule{}
98 m.AddProperties(&m.properties)
Paul Duffina1d60252021-01-21 18:13:43 +000099 android.InitApexModule(m)
Paul Duffinf7f65da2021-03-10 15:00:46 +0000100 android.InitSdkAwareModule(m)
Martin Stjernholmb79c7f12021-03-17 00:26:25 +0000101 android.InitAndroidArchModule(m, android.HostAndDeviceSupported, android.MultilibCommon)
Paul Duffinc7ef9892021-03-23 23:21:59 +0000102
103 // Perform some consistency checking to ensure that the configuration is correct.
104 android.AddLoadHook(m, func(ctx android.LoadHookContext) {
105 bootImageConsistencyCheck(ctx, m)
106 })
Paul Duffin3451e162021-01-20 15:16:56 +0000107 return m
108}
109
Paul Duffinc7ef9892021-03-23 23:21:59 +0000110func bootImageConsistencyCheck(ctx android.EarlyModuleContext, m *BootImageModule) {
Paul Duffin82886d62021-03-24 01:34:57 +0000111 contents := m.properties.Contents
112 if m.properties.Image_name == nil && len(contents) == 0 {
113 ctx.ModuleErrorf(`neither of the "image_name" and "contents" properties have been supplied, please supply exactly one`)
114 }
115 if m.properties.Image_name != nil && len(contents) != 0 {
116 ctx.ModuleErrorf(`both of the "image_name" and "contents" properties have been supplied, please supply exactly one`)
117 }
Paul Duffinc7ef9892021-03-23 23:21:59 +0000118 imageName := proptools.String(m.properties.Image_name)
119 if imageName == "art" {
120 // Get the configuration for the art apex jars. Do not use getImageConfig(ctx) here as this is
121 // too early in the Soong processing for that to work.
122 global := dexpreopt.GetGlobalConfig(ctx)
123 modules := global.ArtApexJars
124
125 // Make sure that the apex specified in the configuration is consistent and is one for which
126 // this boot image is available.
127 jars := []string{}
128 commonApex := ""
129 for i := 0; i < modules.Len(); i++ {
130 apex := modules.Apex(i)
131 jar := modules.Jar(i)
132 if apex == "platform" {
133 ctx.ModuleErrorf("ArtApexJars is invalid as it requests a platform variant of %q", jar)
134 continue
135 }
136 if !m.AvailableFor(apex) {
137 ctx.ModuleErrorf("incompatible with ArtApexJars which expects this to be in apex %q but this is only in apexes %q",
138 apex, m.ApexAvailable())
139 continue
140 }
141 if commonApex == "" {
142 commonApex = apex
143 } else if commonApex != apex {
144 ctx.ModuleErrorf("ArtApexJars configuration is inconsistent, expected all jars to be in the same apex but it specifies apex %q and %q",
145 commonApex, apex)
146 }
147 jars = append(jars, jar)
148 }
149
150 // Store the jars in the Contents property so that they can be used to add dependencies.
151 m.properties.Contents = jars
152 }
153}
154
Paul Duffin3451e162021-01-20 15:16:56 +0000155var BootImageInfoProvider = blueprint.NewProvider(BootImageInfo{})
156
157type BootImageInfo struct {
158 // The image config, internal to this module (and the dex_bootjars singleton).
Paul Duffina1d60252021-01-21 18:13:43 +0000159 //
160 // Will be nil if the BootImageInfo has not been provided for a specific module. That can occur
161 // when SkipDexpreoptBootJars(ctx) returns true.
Paul Duffin3451e162021-01-20 15:16:56 +0000162 imageConfig *bootImageConfig
163}
164
165func (i BootImageInfo) Modules() android.ConfiguredJarList {
166 return i.imageConfig.modules
167}
168
Paul Duffina1d60252021-01-21 18:13:43 +0000169// Get a map from ArchType to the associated boot image's contents for Android.
170//
171// Extension boot images only return their own files, not the files of the boot images they extend.
172func (i BootImageInfo) AndroidBootImageFilesByArchType() map[android.ArchType]android.OutputPaths {
173 files := map[android.ArchType]android.OutputPaths{}
174 if i.imageConfig != nil {
175 for _, variant := range i.imageConfig.variants {
176 // We also generate boot images for host (for testing), but we don't need those in the apex.
177 // TODO(b/177892522) - consider changing this to check Os.OsClass = android.Device
178 if variant.target.Os == android.Android {
179 files[variant.target.Arch.ArchType] = variant.imagesDeps
180 }
181 }
182 }
183 return files
184}
185
186func (b *BootImageModule) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
187 tag := ctx.OtherModuleDependencyTag(dep)
Paul Duffinc7ef9892021-03-23 23:21:59 +0000188 if tag == bootImageContentDepTag {
Paul Duffin4d101b62021-03-24 15:42:20 +0000189 // Boot image contents are automatically added to apex.
190 return true
Paul Duffinc7ef9892021-03-23 23:21:59 +0000191 }
Bob Badour07065cd2021-02-05 19:59:11 -0800192 if android.IsMetaDependencyTag(tag) {
193 // Cross-cutting metadata dependencies are metadata.
194 return false
195 }
Paul Duffina1d60252021-01-21 18:13:43 +0000196 panic(fmt.Errorf("boot_image module %q should not have a dependency on %q via tag %s", b, dep, android.PrettyPrintTag(tag)))
197}
198
199func (b *BootImageModule) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion android.ApiLevel) error {
200 return nil
201}
202
203func (b *BootImageModule) DepsMutator(ctx android.BottomUpMutatorContext) {
Paul Duffinc7ef9892021-03-23 23:21:59 +0000204 ctx.AddDependency(ctx.Module(), bootImageContentDepTag, b.properties.Contents...)
205
Paul Duffina1d60252021-01-21 18:13:43 +0000206 if SkipDexpreoptBootJars(ctx) {
207 return
208 }
209
210 // Add a dependency onto the dex2oat tool which is needed for creating the boot image. The
211 // path is retrieved from the dependency by GetGlobalSoongConfig(ctx).
212 dexpreopt.RegisterToolDeps(ctx)
213}
214
Paul Duffin3451e162021-01-20 15:16:56 +0000215func (b *BootImageModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
216 // Nothing to do if skipping the dexpreopt of boot image jars.
217 if SkipDexpreoptBootJars(ctx) {
218 return
219 }
220
Paul Duffina1d60252021-01-21 18:13:43 +0000221 // Force the GlobalSoongConfig to be created and cached for use by the dex_bootjars
222 // GenerateSingletonBuildActions method as it cannot create it for itself.
223 dexpreopt.GetGlobalSoongConfig(ctx)
224
Paul Duffin64be7bb2021-03-23 23:06:38 +0000225 imageConfig := b.getImageConfig(ctx)
Paul Duffin3451e162021-01-20 15:16:56 +0000226 if imageConfig == nil {
Paul Duffin3451e162021-01-20 15:16:56 +0000227 return
228 }
229
230 // Construct the boot image info from the config.
231 info := BootImageInfo{imageConfig: imageConfig}
232
233 // Make it available for other modules.
234 ctx.SetProvider(BootImageInfoProvider, info)
235}
Paul Duffinf7f65da2021-03-10 15:00:46 +0000236
Paul Duffin64be7bb2021-03-23 23:06:38 +0000237func (b *BootImageModule) getImageConfig(ctx android.EarlyModuleContext) *bootImageConfig {
238 // Get a map of the image configs that are supported.
239 imageConfigs := genBootImageConfigs(ctx)
240
241 // Retrieve the config for this image.
242 imageNamePtr := b.properties.Image_name
243 if imageNamePtr == nil {
244 return nil
245 }
246
247 imageName := *imageNamePtr
248 imageConfig := imageConfigs[imageName]
249 if imageConfig == nil {
250 ctx.PropertyErrorf("image_name", "Unknown image name %q, expected one of %s", imageName, strings.Join(android.SortedStringKeys(imageConfigs), ", "))
251 return nil
252 }
253 return imageConfig
254}
255
Paul Duffinf7f65da2021-03-10 15:00:46 +0000256type bootImageMemberType struct {
257 android.SdkMemberTypeBase
258}
259
260func (b *bootImageMemberType) AddDependencies(mctx android.BottomUpMutatorContext, dependencyTag blueprint.DependencyTag, names []string) {
261 mctx.AddVariationDependencies(nil, dependencyTag, names...)
262}
263
264func (b *bootImageMemberType) IsInstance(module android.Module) bool {
265 _, ok := module.(*BootImageModule)
266 return ok
267}
268
269func (b *bootImageMemberType) AddPrebuiltModule(ctx android.SdkMemberContext, member android.SdkMember) android.BpModule {
Paul Duffin4b64ba02021-03-29 11:02:53 +0100270 if b.PropertyName == "boot_images" {
271 return ctx.SnapshotBuilder().AddPrebuiltModule(member, "prebuilt_boot_image")
272 } else {
273 return ctx.SnapshotBuilder().AddPrebuiltModule(member, "prebuilt_bootclasspath_fragment")
274 }
Paul Duffinf7f65da2021-03-10 15:00:46 +0000275}
276
277func (b *bootImageMemberType) CreateVariantPropertiesStruct() android.SdkMemberProperties {
278 return &bootImageSdkMemberProperties{}
279}
280
281type bootImageSdkMemberProperties struct {
282 android.SdkMemberPropertiesBase
283
Paul Duffin64be7bb2021-03-23 23:06:38 +0000284 Image_name *string
Paul Duffinf7f65da2021-03-10 15:00:46 +0000285}
286
287func (b *bootImageSdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) {
288 module := variant.(*BootImageModule)
289
290 b.Image_name = module.properties.Image_name
291}
292
293func (b *bootImageSdkMemberProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) {
Paul Duffin64be7bb2021-03-23 23:06:38 +0000294 if b.Image_name != nil {
295 propertySet.AddProperty("image_name", *b.Image_name)
Paul Duffinf7f65da2021-03-10 15:00:46 +0000296 }
297}
298
299var _ android.SdkMemberType = (*bootImageMemberType)(nil)
300
301// A prebuilt version of the boot image module.
302//
303// At the moment this is basically just a boot image module that can be used as a prebuilt.
304// Eventually as more functionality is migrated into the boot image module from the singleton then
305// this will diverge.
306type prebuiltBootImageModule struct {
307 BootImageModule
308 prebuilt android.Prebuilt
309}
310
311func (module *prebuiltBootImageModule) Prebuilt() *android.Prebuilt {
312 return &module.prebuilt
313}
314
315func (module *prebuiltBootImageModule) Name() string {
316 return module.prebuilt.Name(module.ModuleBase.Name())
317}
318
319func prebuiltBootImageFactory() android.Module {
320 m := &prebuiltBootImageModule{}
321 m.AddProperties(&m.properties)
Paul Duffinf7f65da2021-03-10 15:00:46 +0000322 // This doesn't actually have any prebuilt files of its own so pass a placeholder for the srcs
323 // array.
324 android.InitPrebuiltModule(m, &[]string{"placeholder"})
325 android.InitApexModule(m)
326 android.InitSdkAwareModule(m)
Martin Stjernholmb79c7f12021-03-17 00:26:25 +0000327 android.InitAndroidArchModule(m, android.HostAndDeviceSupported, android.MultilibCommon)
Paul Duffinc7ef9892021-03-23 23:21:59 +0000328
329 // Perform some consistency checking to ensure that the configuration is correct.
330 android.AddLoadHook(m, func(ctx android.LoadHookContext) {
331 bootImageConsistencyCheck(ctx, &m.BootImageModule)
332 })
Paul Duffinf7f65da2021-03-10 15:00:46 +0000333 return m
334}