blob: 8594792b52c91fbfcd9ba96d0ad79f7af6885efa [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 //
76 // 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.
82 Contents []string `blueprint:"mutated"`
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) {
107 imageName := proptools.String(m.properties.Image_name)
108 if imageName == "art" {
109 // Get the configuration for the art apex jars. Do not use getImageConfig(ctx) here as this is
110 // too early in the Soong processing for that to work.
111 global := dexpreopt.GetGlobalConfig(ctx)
112 modules := global.ArtApexJars
113
114 // Make sure that the apex specified in the configuration is consistent and is one for which
115 // this boot image is available.
116 jars := []string{}
117 commonApex := ""
118 for i := 0; i < modules.Len(); i++ {
119 apex := modules.Apex(i)
120 jar := modules.Jar(i)
121 if apex == "platform" {
122 ctx.ModuleErrorf("ArtApexJars is invalid as it requests a platform variant of %q", jar)
123 continue
124 }
125 if !m.AvailableFor(apex) {
126 ctx.ModuleErrorf("incompatible with ArtApexJars which expects this to be in apex %q but this is only in apexes %q",
127 apex, m.ApexAvailable())
128 continue
129 }
130 if commonApex == "" {
131 commonApex = apex
132 } else if commonApex != apex {
133 ctx.ModuleErrorf("ArtApexJars configuration is inconsistent, expected all jars to be in the same apex but it specifies apex %q and %q",
134 commonApex, apex)
135 }
136 jars = append(jars, jar)
137 }
138
139 // Store the jars in the Contents property so that they can be used to add dependencies.
140 m.properties.Contents = jars
141 }
142}
143
Paul Duffin3451e162021-01-20 15:16:56 +0000144var BootImageInfoProvider = blueprint.NewProvider(BootImageInfo{})
145
146type BootImageInfo struct {
147 // The image config, internal to this module (and the dex_bootjars singleton).
Paul Duffina1d60252021-01-21 18:13:43 +0000148 //
149 // Will be nil if the BootImageInfo has not been provided for a specific module. That can occur
150 // when SkipDexpreoptBootJars(ctx) returns true.
Paul Duffin3451e162021-01-20 15:16:56 +0000151 imageConfig *bootImageConfig
152}
153
154func (i BootImageInfo) Modules() android.ConfiguredJarList {
155 return i.imageConfig.modules
156}
157
Paul Duffina1d60252021-01-21 18:13:43 +0000158// Get a map from ArchType to the associated boot image's contents for Android.
159//
160// Extension boot images only return their own files, not the files of the boot images they extend.
161func (i BootImageInfo) AndroidBootImageFilesByArchType() map[android.ArchType]android.OutputPaths {
162 files := map[android.ArchType]android.OutputPaths{}
163 if i.imageConfig != nil {
164 for _, variant := range i.imageConfig.variants {
165 // We also generate boot images for host (for testing), but we don't need those in the apex.
166 // TODO(b/177892522) - consider changing this to check Os.OsClass = android.Device
167 if variant.target.Os == android.Android {
168 files[variant.target.Arch.ArchType] = variant.imagesDeps
169 }
170 }
171 }
172 return files
173}
174
175func (b *BootImageModule) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
176 tag := ctx.OtherModuleDependencyTag(dep)
Paul Duffinc7ef9892021-03-23 23:21:59 +0000177 if tag == bootImageContentDepTag {
178 // Boot image contents are not automatically added to apex, yet.
179 return false
180 }
Bob Badour07065cd2021-02-05 19:59:11 -0800181 if android.IsMetaDependencyTag(tag) {
182 // Cross-cutting metadata dependencies are metadata.
183 return false
184 }
Paul Duffina1d60252021-01-21 18:13:43 +0000185 panic(fmt.Errorf("boot_image module %q should not have a dependency on %q via tag %s", b, dep, android.PrettyPrintTag(tag)))
186}
187
188func (b *BootImageModule) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion android.ApiLevel) error {
189 return nil
190}
191
192func (b *BootImageModule) DepsMutator(ctx android.BottomUpMutatorContext) {
Paul Duffinc7ef9892021-03-23 23:21:59 +0000193 ctx.AddDependency(ctx.Module(), bootImageContentDepTag, b.properties.Contents...)
194
Paul Duffina1d60252021-01-21 18:13:43 +0000195 if SkipDexpreoptBootJars(ctx) {
196 return
197 }
198
199 // Add a dependency onto the dex2oat tool which is needed for creating the boot image. The
200 // path is retrieved from the dependency by GetGlobalSoongConfig(ctx).
201 dexpreopt.RegisterToolDeps(ctx)
202}
203
Paul Duffin3451e162021-01-20 15:16:56 +0000204func (b *BootImageModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
205 // Nothing to do if skipping the dexpreopt of boot image jars.
206 if SkipDexpreoptBootJars(ctx) {
207 return
208 }
209
Paul Duffina1d60252021-01-21 18:13:43 +0000210 // Force the GlobalSoongConfig to be created and cached for use by the dex_bootjars
211 // GenerateSingletonBuildActions method as it cannot create it for itself.
212 dexpreopt.GetGlobalSoongConfig(ctx)
213
Paul Duffin64be7bb2021-03-23 23:06:38 +0000214 imageConfig := b.getImageConfig(ctx)
Paul Duffin3451e162021-01-20 15:16:56 +0000215 if imageConfig == nil {
Paul Duffin3451e162021-01-20 15:16:56 +0000216 return
217 }
218
219 // Construct the boot image info from the config.
220 info := BootImageInfo{imageConfig: imageConfig}
221
222 // Make it available for other modules.
223 ctx.SetProvider(BootImageInfoProvider, info)
224}
Paul Duffinf7f65da2021-03-10 15:00:46 +0000225
Paul Duffin64be7bb2021-03-23 23:06:38 +0000226func (b *BootImageModule) getImageConfig(ctx android.EarlyModuleContext) *bootImageConfig {
227 // Get a map of the image configs that are supported.
228 imageConfigs := genBootImageConfigs(ctx)
229
230 // Retrieve the config for this image.
231 imageNamePtr := b.properties.Image_name
232 if imageNamePtr == nil {
233 return nil
234 }
235
236 imageName := *imageNamePtr
237 imageConfig := imageConfigs[imageName]
238 if imageConfig == nil {
239 ctx.PropertyErrorf("image_name", "Unknown image name %q, expected one of %s", imageName, strings.Join(android.SortedStringKeys(imageConfigs), ", "))
240 return nil
241 }
242 return imageConfig
243}
244
Paul Duffinf7f65da2021-03-10 15:00:46 +0000245type bootImageMemberType struct {
246 android.SdkMemberTypeBase
247}
248
249func (b *bootImageMemberType) AddDependencies(mctx android.BottomUpMutatorContext, dependencyTag blueprint.DependencyTag, names []string) {
250 mctx.AddVariationDependencies(nil, dependencyTag, names...)
251}
252
253func (b *bootImageMemberType) IsInstance(module android.Module) bool {
254 _, ok := module.(*BootImageModule)
255 return ok
256}
257
258func (b *bootImageMemberType) AddPrebuiltModule(ctx android.SdkMemberContext, member android.SdkMember) android.BpModule {
Paul Duffin4b64ba02021-03-29 11:02:53 +0100259 if b.PropertyName == "boot_images" {
260 return ctx.SnapshotBuilder().AddPrebuiltModule(member, "prebuilt_boot_image")
261 } else {
262 return ctx.SnapshotBuilder().AddPrebuiltModule(member, "prebuilt_bootclasspath_fragment")
263 }
Paul Duffinf7f65da2021-03-10 15:00:46 +0000264}
265
266func (b *bootImageMemberType) CreateVariantPropertiesStruct() android.SdkMemberProperties {
267 return &bootImageSdkMemberProperties{}
268}
269
270type bootImageSdkMemberProperties struct {
271 android.SdkMemberPropertiesBase
272
Paul Duffin64be7bb2021-03-23 23:06:38 +0000273 Image_name *string
Paul Duffinf7f65da2021-03-10 15:00:46 +0000274}
275
276func (b *bootImageSdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) {
277 module := variant.(*BootImageModule)
278
279 b.Image_name = module.properties.Image_name
280}
281
282func (b *bootImageSdkMemberProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) {
Paul Duffin64be7bb2021-03-23 23:06:38 +0000283 if b.Image_name != nil {
284 propertySet.AddProperty("image_name", *b.Image_name)
Paul Duffinf7f65da2021-03-10 15:00:46 +0000285 }
286}
287
288var _ android.SdkMemberType = (*bootImageMemberType)(nil)
289
290// A prebuilt version of the boot image module.
291//
292// At the moment this is basically just a boot image module that can be used as a prebuilt.
293// Eventually as more functionality is migrated into the boot image module from the singleton then
294// this will diverge.
295type prebuiltBootImageModule struct {
296 BootImageModule
297 prebuilt android.Prebuilt
298}
299
300func (module *prebuiltBootImageModule) Prebuilt() *android.Prebuilt {
301 return &module.prebuilt
302}
303
304func (module *prebuiltBootImageModule) Name() string {
305 return module.prebuilt.Name(module.ModuleBase.Name())
306}
307
308func prebuiltBootImageFactory() android.Module {
309 m := &prebuiltBootImageModule{}
310 m.AddProperties(&m.properties)
Paul Duffinf7f65da2021-03-10 15:00:46 +0000311 // This doesn't actually have any prebuilt files of its own so pass a placeholder for the srcs
312 // array.
313 android.InitPrebuiltModule(m, &[]string{"placeholder"})
314 android.InitApexModule(m)
315 android.InitSdkAwareModule(m)
Martin Stjernholmb79c7f12021-03-17 00:26:25 +0000316 android.InitAndroidArchModule(m, android.HostAndDeviceSupported, android.MultilibCommon)
Paul Duffinc7ef9892021-03-23 23:21:59 +0000317
318 // Perform some consistency checking to ensure that the configuration is correct.
319 android.AddLoadHook(m, func(ctx android.LoadHookContext) {
320 bootImageConsistencyCheck(ctx, &m.BootImageModule)
321 })
Paul Duffinf7f65da2021-03-10 15:00:46 +0000322 return m
323}