blob: a14538b6204424fe0ac40ec09bc29cb357897f64 [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 Duffin65898052021-04-20 22:47:03 +010056type bootclasspathFragmentContentDependencyTag struct {
Paul Duffinc7ef9892021-03-23 23:21:59 +000057 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.
Paul Duffin65898052021-04-20 22:47:03 +010065func (b bootclasspathFragmentContentDependencyTag) ExcludeFromVisibilityEnforcement() {
66}
67
68// The bootclasspath_fragment contents must never depend on prebuilts.
69func (b bootclasspathFragmentContentDependencyTag) ReplaceSourceWithPrebuilt() bool {
70 return false
Paul Duffinc7ef9892021-03-23 23:21:59 +000071}
72
73// The tag used for the dependency between the boot image module and its contents.
Paul Duffin65898052021-04-20 22:47:03 +010074var bootclasspathFragmentContentDepTag = bootclasspathFragmentContentDependencyTag{}
Paul Duffinc7ef9892021-03-23 23:21:59 +000075
Paul Duffin65898052021-04-20 22:47:03 +010076var _ android.ExcludeFromVisibilityEnforcementTag = bootclasspathFragmentContentDepTag
77var _ android.ReplaceSourceWithPrebuilt = bootclasspathFragmentContentDepTag
Paul Duffinc7ef9892021-03-23 23:21:59 +000078
Paul Duffin65898052021-04-20 22:47:03 +010079func IsBootclasspathFragmentContentDepTag(tag blueprint.DependencyTag) bool {
80 return tag == bootclasspathFragmentContentDepTag
Paul Duffin4d101b62021-03-24 15:42:20 +000081}
82
Paul Duffin3451e162021-01-20 15:16:56 +000083type bootImageProperties struct {
84 // The name of the image this represents.
85 //
Paul Duffin82886d62021-03-24 01:34:57 +000086 // If specified then it must be one of "art" or "boot".
Paul Duffin64be7bb2021-03-23 23:06:38 +000087 Image_name *string
Paul Duffinc7ef9892021-03-23 23:21:59 +000088
89 // The contents of this boot image, could be either java_library, java_sdk_library, or boot_image.
90 //
91 // The order of this list matters as it is the order that is used in the bootclasspath.
Paul Duffin82886d62021-03-24 01:34:57 +000092 Contents []string
Paul Duffin9b381ef2021-04-08 23:01:37 +010093
94 Hidden_api HiddenAPIFlagFileProperties
Paul Duffin3451e162021-01-20 15:16:56 +000095}
96
97type BootImageModule struct {
98 android.ModuleBase
Paul Duffina1d60252021-01-21 18:13:43 +000099 android.ApexModuleBase
Paul Duffinf7f65da2021-03-10 15:00:46 +0000100 android.SdkBase
Paul Duffin3451e162021-01-20 15:16:56 +0000101 properties bootImageProperties
102}
103
104func bootImageFactory() android.Module {
105 m := &BootImageModule{}
106 m.AddProperties(&m.properties)
Paul Duffina1d60252021-01-21 18:13:43 +0000107 android.InitApexModule(m)
Paul Duffinf7f65da2021-03-10 15:00:46 +0000108 android.InitSdkAwareModule(m)
Martin Stjernholmb79c7f12021-03-17 00:26:25 +0000109 android.InitAndroidArchModule(m, android.HostAndDeviceSupported, android.MultilibCommon)
Paul Duffinc7ef9892021-03-23 23:21:59 +0000110
111 // Perform some consistency checking to ensure that the configuration is correct.
112 android.AddLoadHook(m, func(ctx android.LoadHookContext) {
113 bootImageConsistencyCheck(ctx, m)
114 })
Paul Duffin3451e162021-01-20 15:16:56 +0000115 return m
116}
117
Paul Duffinc7ef9892021-03-23 23:21:59 +0000118func bootImageConsistencyCheck(ctx android.EarlyModuleContext, m *BootImageModule) {
Paul Duffin82886d62021-03-24 01:34:57 +0000119 contents := m.properties.Contents
120 if m.properties.Image_name == nil && len(contents) == 0 {
121 ctx.ModuleErrorf(`neither of the "image_name" and "contents" properties have been supplied, please supply exactly one`)
122 }
123 if m.properties.Image_name != nil && len(contents) != 0 {
124 ctx.ModuleErrorf(`both of the "image_name" and "contents" properties have been supplied, please supply exactly one`)
125 }
Paul Duffinc7ef9892021-03-23 23:21:59 +0000126 imageName := proptools.String(m.properties.Image_name)
127 if imageName == "art" {
128 // Get the configuration for the art apex jars. Do not use getImageConfig(ctx) here as this is
129 // too early in the Soong processing for that to work.
130 global := dexpreopt.GetGlobalConfig(ctx)
131 modules := global.ArtApexJars
132
133 // Make sure that the apex specified in the configuration is consistent and is one for which
134 // this boot image is available.
135 jars := []string{}
136 commonApex := ""
137 for i := 0; i < modules.Len(); i++ {
138 apex := modules.Apex(i)
139 jar := modules.Jar(i)
140 if apex == "platform" {
141 ctx.ModuleErrorf("ArtApexJars is invalid as it requests a platform variant of %q", jar)
142 continue
143 }
144 if !m.AvailableFor(apex) {
145 ctx.ModuleErrorf("incompatible with ArtApexJars which expects this to be in apex %q but this is only in apexes %q",
146 apex, m.ApexAvailable())
147 continue
148 }
149 if commonApex == "" {
150 commonApex = apex
151 } else if commonApex != apex {
152 ctx.ModuleErrorf("ArtApexJars configuration is inconsistent, expected all jars to be in the same apex but it specifies apex %q and %q",
153 commonApex, apex)
154 }
155 jars = append(jars, jar)
156 }
157
158 // Store the jars in the Contents property so that they can be used to add dependencies.
159 m.properties.Contents = jars
160 }
161}
162
Paul Duffin3451e162021-01-20 15:16:56 +0000163var BootImageInfoProvider = blueprint.NewProvider(BootImageInfo{})
164
165type BootImageInfo struct {
166 // The image config, internal to this module (and the dex_bootjars singleton).
Paul Duffina1d60252021-01-21 18:13:43 +0000167 //
168 // Will be nil if the BootImageInfo has not been provided for a specific module. That can occur
169 // when SkipDexpreoptBootJars(ctx) returns true.
Paul Duffin3451e162021-01-20 15:16:56 +0000170 imageConfig *bootImageConfig
171}
172
173func (i BootImageInfo) Modules() android.ConfiguredJarList {
174 return i.imageConfig.modules
175}
176
Paul Duffina1d60252021-01-21 18:13:43 +0000177// Get a map from ArchType to the associated boot image's contents for Android.
178//
179// Extension boot images only return their own files, not the files of the boot images they extend.
180func (i BootImageInfo) AndroidBootImageFilesByArchType() map[android.ArchType]android.OutputPaths {
181 files := map[android.ArchType]android.OutputPaths{}
182 if i.imageConfig != nil {
183 for _, variant := range i.imageConfig.variants {
184 // We also generate boot images for host (for testing), but we don't need those in the apex.
185 // TODO(b/177892522) - consider changing this to check Os.OsClass = android.Device
186 if variant.target.Os == android.Android {
187 files[variant.target.Arch.ArchType] = variant.imagesDeps
188 }
189 }
190 }
191 return files
192}
193
194func (b *BootImageModule) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
195 tag := ctx.OtherModuleDependencyTag(dep)
Paul Duffin65898052021-04-20 22:47:03 +0100196 if IsBootclasspathFragmentContentDepTag(tag) {
Paul Duffin4d101b62021-03-24 15:42:20 +0000197 // Boot image contents are automatically added to apex.
198 return true
Paul Duffinc7ef9892021-03-23 23:21:59 +0000199 }
Bob Badour07065cd2021-02-05 19:59:11 -0800200 if android.IsMetaDependencyTag(tag) {
201 // Cross-cutting metadata dependencies are metadata.
202 return false
203 }
Paul Duffina1d60252021-01-21 18:13:43 +0000204 panic(fmt.Errorf("boot_image module %q should not have a dependency on %q via tag %s", b, dep, android.PrettyPrintTag(tag)))
205}
206
207func (b *BootImageModule) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion android.ApiLevel) error {
208 return nil
209}
210
Paul Duffin65898052021-04-20 22:47:03 +0100211// ComponentDepsMutator adds dependencies onto modules before any prebuilt modules without a
212// corresponding source module are renamed. This means that adding a dependency using a name without
213// a prebuilt_ prefix will always resolve to a source module and when using a name with that prefix
214// it will always resolve to a prebuilt module.
215func (b *BootImageModule) ComponentDepsMutator(ctx android.BottomUpMutatorContext) {
216 module := ctx.Module()
217 _, isSourceModule := module.(*BootImageModule)
218
219 for _, name := range b.properties.Contents {
220 // A bootclasspath_fragment must depend only on other source modules, while the
221 // prebuilt_bootclasspath_fragment must only depend on other prebuilt modules.
Paul Duffina9dd6fa2021-04-22 17:25:57 +0100222 //
223 // TODO(b/177892522) - avoid special handling of jacocoagent.
224 if !isSourceModule && name != "jacocoagent" {
Paul Duffin65898052021-04-20 22:47:03 +0100225 name = android.PrebuiltNameFromSource(name)
226 }
227 ctx.AddDependency(module, bootclasspathFragmentContentDepTag, name)
228 }
229
230}
231
Paul Duffina1d60252021-01-21 18:13:43 +0000232func (b *BootImageModule) DepsMutator(ctx android.BottomUpMutatorContext) {
Paul Duffinc7ef9892021-03-23 23:21:59 +0000233
Paul Duffina1d60252021-01-21 18:13:43 +0000234 if SkipDexpreoptBootJars(ctx) {
235 return
236 }
237
238 // Add a dependency onto the dex2oat tool which is needed for creating the boot image. The
239 // path is retrieved from the dependency by GetGlobalSoongConfig(ctx).
240 dexpreopt.RegisterToolDeps(ctx)
241}
242
Paul Duffin3451e162021-01-20 15:16:56 +0000243func (b *BootImageModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
Paul Duffin9b381ef2021-04-08 23:01:37 +0100244 // Perform hidden API processing.
245 b.generateHiddenAPIBuildActions(ctx)
246
Paul Duffin3451e162021-01-20 15:16:56 +0000247 // Nothing to do if skipping the dexpreopt of boot image jars.
248 if SkipDexpreoptBootJars(ctx) {
249 return
250 }
251
Paul Duffina1d60252021-01-21 18:13:43 +0000252 // Force the GlobalSoongConfig to be created and cached for use by the dex_bootjars
253 // GenerateSingletonBuildActions method as it cannot create it for itself.
254 dexpreopt.GetGlobalSoongConfig(ctx)
255
Paul Duffin64be7bb2021-03-23 23:06:38 +0000256 imageConfig := b.getImageConfig(ctx)
Paul Duffin3451e162021-01-20 15:16:56 +0000257 if imageConfig == nil {
Paul Duffin3451e162021-01-20 15:16:56 +0000258 return
259 }
260
261 // Construct the boot image info from the config.
262 info := BootImageInfo{imageConfig: imageConfig}
263
264 // Make it available for other modules.
265 ctx.SetProvider(BootImageInfoProvider, info)
266}
Paul Duffinf7f65da2021-03-10 15:00:46 +0000267
Paul Duffin64be7bb2021-03-23 23:06:38 +0000268func (b *BootImageModule) getImageConfig(ctx android.EarlyModuleContext) *bootImageConfig {
269 // Get a map of the image configs that are supported.
270 imageConfigs := genBootImageConfigs(ctx)
271
272 // Retrieve the config for this image.
273 imageNamePtr := b.properties.Image_name
274 if imageNamePtr == nil {
275 return nil
276 }
277
278 imageName := *imageNamePtr
279 imageConfig := imageConfigs[imageName]
280 if imageConfig == nil {
281 ctx.PropertyErrorf("image_name", "Unknown image name %q, expected one of %s", imageName, strings.Join(android.SortedStringKeys(imageConfigs), ", "))
282 return nil
283 }
284 return imageConfig
285}
286
Paul Duffin9b381ef2021-04-08 23:01:37 +0100287// generateHiddenAPIBuildActions generates all the hidden API related build rules.
288func (b *BootImageModule) generateHiddenAPIBuildActions(ctx android.ModuleContext) {
289 // Resolve the properties to paths.
290 flagFileInfo := b.properties.Hidden_api.hiddenAPIFlagFileInfo(ctx)
291
292 // Store the information for use by platform_bootclasspath.
293 ctx.SetProvider(hiddenAPIFlagFileInfoProvider, flagFileInfo)
294}
295
Paul Duffinf7f65da2021-03-10 15:00:46 +0000296type bootImageMemberType struct {
297 android.SdkMemberTypeBase
298}
299
300func (b *bootImageMemberType) AddDependencies(mctx android.BottomUpMutatorContext, dependencyTag blueprint.DependencyTag, names []string) {
301 mctx.AddVariationDependencies(nil, dependencyTag, names...)
302}
303
304func (b *bootImageMemberType) IsInstance(module android.Module) bool {
305 _, ok := module.(*BootImageModule)
306 return ok
307}
308
309func (b *bootImageMemberType) AddPrebuiltModule(ctx android.SdkMemberContext, member android.SdkMember) android.BpModule {
Paul Duffin4b64ba02021-03-29 11:02:53 +0100310 if b.PropertyName == "boot_images" {
311 return ctx.SnapshotBuilder().AddPrebuiltModule(member, "prebuilt_boot_image")
312 } else {
313 return ctx.SnapshotBuilder().AddPrebuiltModule(member, "prebuilt_bootclasspath_fragment")
314 }
Paul Duffinf7f65da2021-03-10 15:00:46 +0000315}
316
317func (b *bootImageMemberType) CreateVariantPropertiesStruct() android.SdkMemberProperties {
318 return &bootImageSdkMemberProperties{}
319}
320
321type bootImageSdkMemberProperties struct {
322 android.SdkMemberPropertiesBase
323
Paul Duffin64be7bb2021-03-23 23:06:38 +0000324 Image_name *string
Paul Duffinf7f65da2021-03-10 15:00:46 +0000325}
326
327func (b *bootImageSdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) {
328 module := variant.(*BootImageModule)
329
330 b.Image_name = module.properties.Image_name
331}
332
333func (b *bootImageSdkMemberProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) {
Paul Duffin64be7bb2021-03-23 23:06:38 +0000334 if b.Image_name != nil {
335 propertySet.AddProperty("image_name", *b.Image_name)
Paul Duffinf7f65da2021-03-10 15:00:46 +0000336 }
337}
338
339var _ android.SdkMemberType = (*bootImageMemberType)(nil)
340
341// A prebuilt version of the boot image module.
342//
343// At the moment this is basically just a boot image module that can be used as a prebuilt.
344// Eventually as more functionality is migrated into the boot image module from the singleton then
345// this will diverge.
346type prebuiltBootImageModule struct {
347 BootImageModule
348 prebuilt android.Prebuilt
349}
350
351func (module *prebuiltBootImageModule) Prebuilt() *android.Prebuilt {
352 return &module.prebuilt
353}
354
355func (module *prebuiltBootImageModule) Name() string {
356 return module.prebuilt.Name(module.ModuleBase.Name())
357}
358
359func prebuiltBootImageFactory() android.Module {
360 m := &prebuiltBootImageModule{}
361 m.AddProperties(&m.properties)
Paul Duffinf7f65da2021-03-10 15:00:46 +0000362 // This doesn't actually have any prebuilt files of its own so pass a placeholder for the srcs
363 // array.
364 android.InitPrebuiltModule(m, &[]string{"placeholder"})
365 android.InitApexModule(m)
366 android.InitSdkAwareModule(m)
Martin Stjernholmb79c7f12021-03-17 00:26:25 +0000367 android.InitAndroidArchModule(m, android.HostAndDeviceSupported, android.MultilibCommon)
Paul Duffinc7ef9892021-03-23 23:21:59 +0000368
369 // Perform some consistency checking to ensure that the configuration is correct.
370 android.AddLoadHook(m, func(ctx android.LoadHookContext) {
371 bootImageConsistencyCheck(ctx, &m.BootImageModule)
372 })
Paul Duffinf7f65da2021-03-10 15:00:46 +0000373 return m
374}