blob: 0fc9c6cb60f1e73b28349268c5ddda04f7e8e345 [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 Duffin3451e162021-01-20 15:16:56 +000073type bootImageProperties struct {
74 // The name of the image this represents.
75 //
Paul Duffin82886d62021-03-24 01:34:57 +000076 // If specified then it must be one of "art" or "boot".
Paul Duffin64be7bb2021-03-23 23:06:38 +000077 Image_name *string
Paul Duffinc7ef9892021-03-23 23:21:59 +000078
79 // The contents of this boot image, could be either java_library, java_sdk_library, or boot_image.
80 //
81 // The order of this list matters as it is the order that is used in the bootclasspath.
Paul Duffin82886d62021-03-24 01:34:57 +000082 Contents []string
Paul Duffin3451e162021-01-20 15:16:56 +000083}
84
85type BootImageModule struct {
86 android.ModuleBase
Paul Duffina1d60252021-01-21 18:13:43 +000087 android.ApexModuleBase
Paul Duffinf7f65da2021-03-10 15:00:46 +000088 android.SdkBase
Paul Duffin3451e162021-01-20 15:16:56 +000089 properties bootImageProperties
90}
91
92func bootImageFactory() android.Module {
93 m := &BootImageModule{}
94 m.AddProperties(&m.properties)
Paul Duffina1d60252021-01-21 18:13:43 +000095 android.InitApexModule(m)
Paul Duffinf7f65da2021-03-10 15:00:46 +000096 android.InitSdkAwareModule(m)
Martin Stjernholmb79c7f12021-03-17 00:26:25 +000097 android.InitAndroidArchModule(m, android.HostAndDeviceSupported, android.MultilibCommon)
Paul Duffinc7ef9892021-03-23 23:21:59 +000098
99 // Perform some consistency checking to ensure that the configuration is correct.
100 android.AddLoadHook(m, func(ctx android.LoadHookContext) {
101 bootImageConsistencyCheck(ctx, m)
102 })
Paul Duffin3451e162021-01-20 15:16:56 +0000103 return m
104}
105
Paul Duffinc7ef9892021-03-23 23:21:59 +0000106func bootImageConsistencyCheck(ctx android.EarlyModuleContext, m *BootImageModule) {
Paul Duffin82886d62021-03-24 01:34:57 +0000107 contents := m.properties.Contents
108 if m.properties.Image_name == nil && len(contents) == 0 {
109 ctx.ModuleErrorf(`neither of the "image_name" and "contents" properties have been supplied, please supply exactly one`)
110 }
111 if m.properties.Image_name != nil && len(contents) != 0 {
112 ctx.ModuleErrorf(`both of the "image_name" and "contents" properties have been supplied, please supply exactly one`)
113 }
Paul Duffinc7ef9892021-03-23 23:21:59 +0000114 imageName := proptools.String(m.properties.Image_name)
115 if imageName == "art" {
116 // Get the configuration for the art apex jars. Do not use getImageConfig(ctx) here as this is
117 // too early in the Soong processing for that to work.
118 global := dexpreopt.GetGlobalConfig(ctx)
119 modules := global.ArtApexJars
120
121 // Make sure that the apex specified in the configuration is consistent and is one for which
122 // this boot image is available.
123 jars := []string{}
124 commonApex := ""
125 for i := 0; i < modules.Len(); i++ {
126 apex := modules.Apex(i)
127 jar := modules.Jar(i)
128 if apex == "platform" {
129 ctx.ModuleErrorf("ArtApexJars is invalid as it requests a platform variant of %q", jar)
130 continue
131 }
132 if !m.AvailableFor(apex) {
133 ctx.ModuleErrorf("incompatible with ArtApexJars which expects this to be in apex %q but this is only in apexes %q",
134 apex, m.ApexAvailable())
135 continue
136 }
137 if commonApex == "" {
138 commonApex = apex
139 } else if commonApex != apex {
140 ctx.ModuleErrorf("ArtApexJars configuration is inconsistent, expected all jars to be in the same apex but it specifies apex %q and %q",
141 commonApex, apex)
142 }
143 jars = append(jars, jar)
144 }
145
146 // Store the jars in the Contents property so that they can be used to add dependencies.
147 m.properties.Contents = jars
148 }
149}
150
Paul Duffin3451e162021-01-20 15:16:56 +0000151var BootImageInfoProvider = blueprint.NewProvider(BootImageInfo{})
152
153type BootImageInfo struct {
154 // The image config, internal to this module (and the dex_bootjars singleton).
Paul Duffina1d60252021-01-21 18:13:43 +0000155 //
156 // Will be nil if the BootImageInfo has not been provided for a specific module. That can occur
157 // when SkipDexpreoptBootJars(ctx) returns true.
Paul Duffin3451e162021-01-20 15:16:56 +0000158 imageConfig *bootImageConfig
159}
160
161func (i BootImageInfo) Modules() android.ConfiguredJarList {
162 return i.imageConfig.modules
163}
164
Paul Duffina1d60252021-01-21 18:13:43 +0000165// Get a map from ArchType to the associated boot image's contents for Android.
166//
167// Extension boot images only return their own files, not the files of the boot images they extend.
168func (i BootImageInfo) AndroidBootImageFilesByArchType() map[android.ArchType]android.OutputPaths {
169 files := map[android.ArchType]android.OutputPaths{}
170 if i.imageConfig != nil {
171 for _, variant := range i.imageConfig.variants {
172 // We also generate boot images for host (for testing), but we don't need those in the apex.
173 // TODO(b/177892522) - consider changing this to check Os.OsClass = android.Device
174 if variant.target.Os == android.Android {
175 files[variant.target.Arch.ArchType] = variant.imagesDeps
176 }
177 }
178 }
179 return files
180}
181
182func (b *BootImageModule) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
183 tag := ctx.OtherModuleDependencyTag(dep)
Paul Duffinc7ef9892021-03-23 23:21:59 +0000184 if tag == bootImageContentDepTag {
185 // Boot image contents are not automatically added to apex, yet.
186 return false
187 }
Bob Badour07065cd2021-02-05 19:59:11 -0800188 if android.IsMetaDependencyTag(tag) {
189 // Cross-cutting metadata dependencies are metadata.
190 return false
191 }
Paul Duffina1d60252021-01-21 18:13:43 +0000192 panic(fmt.Errorf("boot_image module %q should not have a dependency on %q via tag %s", b, dep, android.PrettyPrintTag(tag)))
193}
194
195func (b *BootImageModule) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion android.ApiLevel) error {
196 return nil
197}
198
199func (b *BootImageModule) DepsMutator(ctx android.BottomUpMutatorContext) {
Paul Duffinc7ef9892021-03-23 23:21:59 +0000200 ctx.AddDependency(ctx.Module(), bootImageContentDepTag, b.properties.Contents...)
201
Paul Duffina1d60252021-01-21 18:13:43 +0000202 if SkipDexpreoptBootJars(ctx) {
203 return
204 }
205
206 // Add a dependency onto the dex2oat tool which is needed for creating the boot image. The
207 // path is retrieved from the dependency by GetGlobalSoongConfig(ctx).
208 dexpreopt.RegisterToolDeps(ctx)
209}
210
Paul Duffin3451e162021-01-20 15:16:56 +0000211func (b *BootImageModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
212 // Nothing to do if skipping the dexpreopt of boot image jars.
213 if SkipDexpreoptBootJars(ctx) {
214 return
215 }
216
Paul Duffina1d60252021-01-21 18:13:43 +0000217 // Force the GlobalSoongConfig to be created and cached for use by the dex_bootjars
218 // GenerateSingletonBuildActions method as it cannot create it for itself.
219 dexpreopt.GetGlobalSoongConfig(ctx)
220
Paul Duffin64be7bb2021-03-23 23:06:38 +0000221 imageConfig := b.getImageConfig(ctx)
Paul Duffin3451e162021-01-20 15:16:56 +0000222 if imageConfig == nil {
Paul Duffin3451e162021-01-20 15:16:56 +0000223 return
224 }
225
226 // Construct the boot image info from the config.
227 info := BootImageInfo{imageConfig: imageConfig}
228
229 // Make it available for other modules.
230 ctx.SetProvider(BootImageInfoProvider, info)
231}
Paul Duffinf7f65da2021-03-10 15:00:46 +0000232
Paul Duffin64be7bb2021-03-23 23:06:38 +0000233func (b *BootImageModule) getImageConfig(ctx android.EarlyModuleContext) *bootImageConfig {
234 // Get a map of the image configs that are supported.
235 imageConfigs := genBootImageConfigs(ctx)
236
237 // Retrieve the config for this image.
238 imageNamePtr := b.properties.Image_name
239 if imageNamePtr == nil {
240 return nil
241 }
242
243 imageName := *imageNamePtr
244 imageConfig := imageConfigs[imageName]
245 if imageConfig == nil {
246 ctx.PropertyErrorf("image_name", "Unknown image name %q, expected one of %s", imageName, strings.Join(android.SortedStringKeys(imageConfigs), ", "))
247 return nil
248 }
249 return imageConfig
250}
251
Paul Duffinf7f65da2021-03-10 15:00:46 +0000252type bootImageMemberType struct {
253 android.SdkMemberTypeBase
254}
255
256func (b *bootImageMemberType) AddDependencies(mctx android.BottomUpMutatorContext, dependencyTag blueprint.DependencyTag, names []string) {
257 mctx.AddVariationDependencies(nil, dependencyTag, names...)
258}
259
260func (b *bootImageMemberType) IsInstance(module android.Module) bool {
261 _, ok := module.(*BootImageModule)
262 return ok
263}
264
265func (b *bootImageMemberType) AddPrebuiltModule(ctx android.SdkMemberContext, member android.SdkMember) android.BpModule {
Paul Duffin4b64ba02021-03-29 11:02:53 +0100266 if b.PropertyName == "boot_images" {
267 return ctx.SnapshotBuilder().AddPrebuiltModule(member, "prebuilt_boot_image")
268 } else {
269 return ctx.SnapshotBuilder().AddPrebuiltModule(member, "prebuilt_bootclasspath_fragment")
270 }
Paul Duffinf7f65da2021-03-10 15:00:46 +0000271}
272
273func (b *bootImageMemberType) CreateVariantPropertiesStruct() android.SdkMemberProperties {
274 return &bootImageSdkMemberProperties{}
275}
276
277type bootImageSdkMemberProperties struct {
278 android.SdkMemberPropertiesBase
279
Paul Duffin64be7bb2021-03-23 23:06:38 +0000280 Image_name *string
Paul Duffinf7f65da2021-03-10 15:00:46 +0000281}
282
283func (b *bootImageSdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) {
284 module := variant.(*BootImageModule)
285
286 b.Image_name = module.properties.Image_name
287}
288
289func (b *bootImageSdkMemberProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) {
Paul Duffin64be7bb2021-03-23 23:06:38 +0000290 if b.Image_name != nil {
291 propertySet.AddProperty("image_name", *b.Image_name)
Paul Duffinf7f65da2021-03-10 15:00:46 +0000292 }
293}
294
295var _ android.SdkMemberType = (*bootImageMemberType)(nil)
296
297// A prebuilt version of the boot image module.
298//
299// At the moment this is basically just a boot image module that can be used as a prebuilt.
300// Eventually as more functionality is migrated into the boot image module from the singleton then
301// this will diverge.
302type prebuiltBootImageModule struct {
303 BootImageModule
304 prebuilt android.Prebuilt
305}
306
307func (module *prebuiltBootImageModule) Prebuilt() *android.Prebuilt {
308 return &module.prebuilt
309}
310
311func (module *prebuiltBootImageModule) Name() string {
312 return module.prebuilt.Name(module.ModuleBase.Name())
313}
314
315func prebuiltBootImageFactory() android.Module {
316 m := &prebuiltBootImageModule{}
317 m.AddProperties(&m.properties)
Paul Duffinf7f65da2021-03-10 15:00:46 +0000318 // This doesn't actually have any prebuilt files of its own so pass a placeholder for the srcs
319 // array.
320 android.InitPrebuiltModule(m, &[]string{"placeholder"})
321 android.InitApexModule(m)
322 android.InitSdkAwareModule(m)
Martin Stjernholmb79c7f12021-03-17 00:26:25 +0000323 android.InitAndroidArchModule(m, android.HostAndDeviceSupported, android.MultilibCommon)
Paul Duffinc7ef9892021-03-23 23:21:59 +0000324
325 // Perform some consistency checking to ensure that the configuration is correct.
326 android.AddLoadHook(m, func(ctx android.LoadHookContext) {
327 bootImageConsistencyCheck(ctx, &m.BootImageModule)
328 })
Paul Duffinf7f65da2021-03-10 15:00:46 +0000329 return m
330}