blob: af5c8ff63eff9d2c08faa27a4e6bac4b8df51730 [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.
222 if !isSourceModule {
223 name = android.PrebuiltNameFromSource(name)
224 }
225 ctx.AddDependency(module, bootclasspathFragmentContentDepTag, name)
226 }
227
228}
229
Paul Duffina1d60252021-01-21 18:13:43 +0000230func (b *BootImageModule) DepsMutator(ctx android.BottomUpMutatorContext) {
Paul Duffinc7ef9892021-03-23 23:21:59 +0000231
Paul Duffina1d60252021-01-21 18:13:43 +0000232 if SkipDexpreoptBootJars(ctx) {
233 return
234 }
235
236 // Add a dependency onto the dex2oat tool which is needed for creating the boot image. The
237 // path is retrieved from the dependency by GetGlobalSoongConfig(ctx).
238 dexpreopt.RegisterToolDeps(ctx)
239}
240
Paul Duffin3451e162021-01-20 15:16:56 +0000241func (b *BootImageModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
Paul Duffin9b381ef2021-04-08 23:01:37 +0100242 // Perform hidden API processing.
243 b.generateHiddenAPIBuildActions(ctx)
244
Paul Duffin3451e162021-01-20 15:16:56 +0000245 // Nothing to do if skipping the dexpreopt of boot image jars.
246 if SkipDexpreoptBootJars(ctx) {
247 return
248 }
249
Paul Duffina1d60252021-01-21 18:13:43 +0000250 // Force the GlobalSoongConfig to be created and cached for use by the dex_bootjars
251 // GenerateSingletonBuildActions method as it cannot create it for itself.
252 dexpreopt.GetGlobalSoongConfig(ctx)
253
Paul Duffin64be7bb2021-03-23 23:06:38 +0000254 imageConfig := b.getImageConfig(ctx)
Paul Duffin3451e162021-01-20 15:16:56 +0000255 if imageConfig == nil {
Paul Duffin3451e162021-01-20 15:16:56 +0000256 return
257 }
258
259 // Construct the boot image info from the config.
260 info := BootImageInfo{imageConfig: imageConfig}
261
262 // Make it available for other modules.
263 ctx.SetProvider(BootImageInfoProvider, info)
264}
Paul Duffinf7f65da2021-03-10 15:00:46 +0000265
Paul Duffin64be7bb2021-03-23 23:06:38 +0000266func (b *BootImageModule) getImageConfig(ctx android.EarlyModuleContext) *bootImageConfig {
267 // Get a map of the image configs that are supported.
268 imageConfigs := genBootImageConfigs(ctx)
269
270 // Retrieve the config for this image.
271 imageNamePtr := b.properties.Image_name
272 if imageNamePtr == nil {
273 return nil
274 }
275
276 imageName := *imageNamePtr
277 imageConfig := imageConfigs[imageName]
278 if imageConfig == nil {
279 ctx.PropertyErrorf("image_name", "Unknown image name %q, expected one of %s", imageName, strings.Join(android.SortedStringKeys(imageConfigs), ", "))
280 return nil
281 }
282 return imageConfig
283}
284
Paul Duffin9b381ef2021-04-08 23:01:37 +0100285// generateHiddenAPIBuildActions generates all the hidden API related build rules.
286func (b *BootImageModule) generateHiddenAPIBuildActions(ctx android.ModuleContext) {
287 // Resolve the properties to paths.
288 flagFileInfo := b.properties.Hidden_api.hiddenAPIFlagFileInfo(ctx)
289
290 // Store the information for use by platform_bootclasspath.
291 ctx.SetProvider(hiddenAPIFlagFileInfoProvider, flagFileInfo)
292}
293
Paul Duffinf7f65da2021-03-10 15:00:46 +0000294type bootImageMemberType struct {
295 android.SdkMemberTypeBase
296}
297
298func (b *bootImageMemberType) AddDependencies(mctx android.BottomUpMutatorContext, dependencyTag blueprint.DependencyTag, names []string) {
299 mctx.AddVariationDependencies(nil, dependencyTag, names...)
300}
301
302func (b *bootImageMemberType) IsInstance(module android.Module) bool {
303 _, ok := module.(*BootImageModule)
304 return ok
305}
306
307func (b *bootImageMemberType) AddPrebuiltModule(ctx android.SdkMemberContext, member android.SdkMember) android.BpModule {
Paul Duffin4b64ba02021-03-29 11:02:53 +0100308 if b.PropertyName == "boot_images" {
309 return ctx.SnapshotBuilder().AddPrebuiltModule(member, "prebuilt_boot_image")
310 } else {
311 return ctx.SnapshotBuilder().AddPrebuiltModule(member, "prebuilt_bootclasspath_fragment")
312 }
Paul Duffinf7f65da2021-03-10 15:00:46 +0000313}
314
315func (b *bootImageMemberType) CreateVariantPropertiesStruct() android.SdkMemberProperties {
316 return &bootImageSdkMemberProperties{}
317}
318
319type bootImageSdkMemberProperties struct {
320 android.SdkMemberPropertiesBase
321
Paul Duffina57835e2021-04-19 13:23:06 +0100322 // The image name
Paul Duffin64be7bb2021-03-23 23:06:38 +0000323 Image_name *string
Paul Duffina57835e2021-04-19 13:23:06 +0100324
325 // Contents of the bootclasspath fragment
326 Contents []string
Paul Duffinf7f65da2021-03-10 15:00:46 +0000327}
328
329func (b *bootImageSdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) {
330 module := variant.(*BootImageModule)
331
332 b.Image_name = module.properties.Image_name
Paul Duffina57835e2021-04-19 13:23:06 +0100333 if b.Image_name == nil {
334 // Only one of image_name or contents can be specified. However, if image_name is set then the
335 // contents property is updated to match the configuration used to create the corresponding
336 // boot image. Therefore, contents property is only copied if the image name is not specified.
337 b.Contents = module.properties.Contents
338 }
Paul Duffinf7f65da2021-03-10 15:00:46 +0000339}
340
341func (b *bootImageSdkMemberProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) {
Paul Duffin64be7bb2021-03-23 23:06:38 +0000342 if b.Image_name != nil {
343 propertySet.AddProperty("image_name", *b.Image_name)
Paul Duffinf7f65da2021-03-10 15:00:46 +0000344 }
Paul Duffina57835e2021-04-19 13:23:06 +0100345
346 if len(b.Contents) > 0 {
347 propertySet.AddPropertyWithTag("contents", b.Contents, ctx.SnapshotBuilder().SdkMemberReferencePropertyTag(true))
348 }
Paul Duffinf7f65da2021-03-10 15:00:46 +0000349}
350
351var _ android.SdkMemberType = (*bootImageMemberType)(nil)
352
353// A prebuilt version of the boot image module.
354//
355// At the moment this is basically just a boot image module that can be used as a prebuilt.
356// Eventually as more functionality is migrated into the boot image module from the singleton then
357// this will diverge.
358type prebuiltBootImageModule struct {
359 BootImageModule
360 prebuilt android.Prebuilt
361}
362
363func (module *prebuiltBootImageModule) Prebuilt() *android.Prebuilt {
364 return &module.prebuilt
365}
366
367func (module *prebuiltBootImageModule) Name() string {
368 return module.prebuilt.Name(module.ModuleBase.Name())
369}
370
371func prebuiltBootImageFactory() android.Module {
372 m := &prebuiltBootImageModule{}
373 m.AddProperties(&m.properties)
Paul Duffinf7f65da2021-03-10 15:00:46 +0000374 // This doesn't actually have any prebuilt files of its own so pass a placeholder for the srcs
375 // array.
376 android.InitPrebuiltModule(m, &[]string{"placeholder"})
377 android.InitApexModule(m)
378 android.InitSdkAwareModule(m)
Martin Stjernholmb79c7f12021-03-17 00:26:25 +0000379 android.InitAndroidArchModule(m, android.HostAndDeviceSupported, android.MultilibCommon)
Paul Duffinc7ef9892021-03-23 23:21:59 +0000380
381 // Perform some consistency checking to ensure that the configuration is correct.
382 android.AddLoadHook(m, func(ctx android.LoadHookContext) {
383 bootImageConsistencyCheck(ctx, &m.BootImageModule)
384 })
Paul Duffinf7f65da2021-03-10 15:00:46 +0000385 return m
386}