blob: d0862a961ba120db7793c2ab1b280af99d0921c9 [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 Duffin7c955552021-04-19 13:23:53 +010019 "path/filepath"
Paul Duffin3451e162021-01-20 15:16:56 +000020 "strings"
21
22 "android/soong/android"
Paul Duffina1d60252021-01-21 18:13:43 +000023 "android/soong/dexpreopt"
Paul Duffinc7ef9892021-03-23 23:21:59 +000024 "github.com/google/blueprint/proptools"
Martin Stjernholmb79c7f12021-03-17 00:26:25 +000025
Paul Duffin3451e162021-01-20 15:16:56 +000026 "github.com/google/blueprint"
27)
28
29func init() {
30 RegisterBootImageBuildComponents(android.InitRegistrationContext)
Paul Duffinf7f65da2021-03-10 15:00:46 +000031
Paul Duffin4b64ba02021-03-29 11:02:53 +010032 // TODO(b/177892522): Remove after has been replaced by bootclasspath_fragments
Paul Duffinf7f65da2021-03-10 15:00:46 +000033 android.RegisterSdkMemberType(&bootImageMemberType{
34 SdkMemberTypeBase: android.SdkMemberTypeBase{
35 PropertyName: "boot_images",
36 SupportsSdk: true,
37 },
38 })
Paul Duffin4b64ba02021-03-29 11:02:53 +010039
40 android.RegisterSdkMemberType(&bootImageMemberType{
41 SdkMemberTypeBase: android.SdkMemberTypeBase{
42 PropertyName: "bootclasspath_fragments",
43 SupportsSdk: true,
44 },
45 })
Paul Duffin3451e162021-01-20 15:16:56 +000046}
47
48func RegisterBootImageBuildComponents(ctx android.RegistrationContext) {
Paul Duffin4b64ba02021-03-29 11:02:53 +010049 // TODO(b/177892522): Remove after has been replaced by bootclasspath_fragment
Paul Duffin3451e162021-01-20 15:16:56 +000050 ctx.RegisterModuleType("boot_image", bootImageFactory)
Paul Duffinf7f65da2021-03-10 15:00:46 +000051 ctx.RegisterModuleType("prebuilt_boot_image", prebuiltBootImageFactory)
Paul Duffin4b64ba02021-03-29 11:02:53 +010052
53 ctx.RegisterModuleType("bootclasspath_fragment", bootImageFactory)
54 ctx.RegisterModuleType("prebuilt_bootclasspath_fragment", prebuiltBootImageFactory)
Paul Duffin3451e162021-01-20 15:16:56 +000055}
56
Paul Duffin65898052021-04-20 22:47:03 +010057type bootclasspathFragmentContentDependencyTag struct {
Paul Duffinc7ef9892021-03-23 23:21:59 +000058 blueprint.BaseDependencyTag
59}
60
61// Avoid having to make boot image content visible to the boot image.
62//
63// This is a temporary workaround to make it easier to migrate to boot image modules with proper
64// dependencies.
65// TODO(b/177892522): Remove this and add needed visibility.
Paul Duffin65898052021-04-20 22:47:03 +010066func (b bootclasspathFragmentContentDependencyTag) ExcludeFromVisibilityEnforcement() {
67}
68
69// The bootclasspath_fragment contents must never depend on prebuilts.
70func (b bootclasspathFragmentContentDependencyTag) ReplaceSourceWithPrebuilt() bool {
71 return false
Paul Duffinc7ef9892021-03-23 23:21:59 +000072}
73
74// The tag used for the dependency between the boot image module and its contents.
Paul Duffin65898052021-04-20 22:47:03 +010075var bootclasspathFragmentContentDepTag = bootclasspathFragmentContentDependencyTag{}
Paul Duffinc7ef9892021-03-23 23:21:59 +000076
Paul Duffin65898052021-04-20 22:47:03 +010077var _ android.ExcludeFromVisibilityEnforcementTag = bootclasspathFragmentContentDepTag
78var _ android.ReplaceSourceWithPrebuilt = bootclasspathFragmentContentDepTag
Paul Duffinc7ef9892021-03-23 23:21:59 +000079
Paul Duffin65898052021-04-20 22:47:03 +010080func IsBootclasspathFragmentContentDepTag(tag blueprint.DependencyTag) bool {
81 return tag == bootclasspathFragmentContentDepTag
Paul Duffin4d101b62021-03-24 15:42:20 +000082}
83
Paul Duffin3451e162021-01-20 15:16:56 +000084type bootImageProperties struct {
85 // The name of the image this represents.
86 //
Paul Duffin82886d62021-03-24 01:34:57 +000087 // If specified then it must be one of "art" or "boot".
Paul Duffin64be7bb2021-03-23 23:06:38 +000088 Image_name *string
Paul Duffinc7ef9892021-03-23 23:21:59 +000089
90 // The contents of this boot image, could be either java_library, java_sdk_library, or boot_image.
91 //
92 // The order of this list matters as it is the order that is used in the bootclasspath.
Paul Duffin82886d62021-03-24 01:34:57 +000093 Contents []string
Paul Duffin9b381ef2021-04-08 23:01:37 +010094
95 Hidden_api HiddenAPIFlagFileProperties
Paul Duffin3451e162021-01-20 15:16:56 +000096}
97
98type BootImageModule struct {
99 android.ModuleBase
Paul Duffina1d60252021-01-21 18:13:43 +0000100 android.ApexModuleBase
Paul Duffinf7f65da2021-03-10 15:00:46 +0000101 android.SdkBase
Paul Duffin3451e162021-01-20 15:16:56 +0000102 properties bootImageProperties
103}
104
105func bootImageFactory() android.Module {
106 m := &BootImageModule{}
107 m.AddProperties(&m.properties)
Paul Duffina1d60252021-01-21 18:13:43 +0000108 android.InitApexModule(m)
Paul Duffinf7f65da2021-03-10 15:00:46 +0000109 android.InitSdkAwareModule(m)
Martin Stjernholmb79c7f12021-03-17 00:26:25 +0000110 android.InitAndroidArchModule(m, android.HostAndDeviceSupported, android.MultilibCommon)
Paul Duffinc7ef9892021-03-23 23:21:59 +0000111
112 // Perform some consistency checking to ensure that the configuration is correct.
113 android.AddLoadHook(m, func(ctx android.LoadHookContext) {
114 bootImageConsistencyCheck(ctx, m)
115 })
Paul Duffin3451e162021-01-20 15:16:56 +0000116 return m
117}
118
Paul Duffinc7ef9892021-03-23 23:21:59 +0000119func bootImageConsistencyCheck(ctx android.EarlyModuleContext, m *BootImageModule) {
Paul Duffin82886d62021-03-24 01:34:57 +0000120 contents := m.properties.Contents
121 if m.properties.Image_name == nil && len(contents) == 0 {
122 ctx.ModuleErrorf(`neither of the "image_name" and "contents" properties have been supplied, please supply exactly one`)
123 }
124 if m.properties.Image_name != nil && len(contents) != 0 {
125 ctx.ModuleErrorf(`both of the "image_name" and "contents" properties have been supplied, please supply exactly one`)
126 }
Paul Duffinc7ef9892021-03-23 23:21:59 +0000127 imageName := proptools.String(m.properties.Image_name)
128 if imageName == "art" {
129 // Get the configuration for the art apex jars. Do not use getImageConfig(ctx) here as this is
130 // too early in the Soong processing for that to work.
131 global := dexpreopt.GetGlobalConfig(ctx)
132 modules := global.ArtApexJars
133
134 // Make sure that the apex specified in the configuration is consistent and is one for which
135 // this boot image is available.
136 jars := []string{}
137 commonApex := ""
138 for i := 0; i < modules.Len(); i++ {
139 apex := modules.Apex(i)
140 jar := modules.Jar(i)
141 if apex == "platform" {
142 ctx.ModuleErrorf("ArtApexJars is invalid as it requests a platform variant of %q", jar)
143 continue
144 }
145 if !m.AvailableFor(apex) {
146 ctx.ModuleErrorf("incompatible with ArtApexJars which expects this to be in apex %q but this is only in apexes %q",
147 apex, m.ApexAvailable())
148 continue
149 }
150 if commonApex == "" {
151 commonApex = apex
152 } else if commonApex != apex {
153 ctx.ModuleErrorf("ArtApexJars configuration is inconsistent, expected all jars to be in the same apex but it specifies apex %q and %q",
154 commonApex, apex)
155 }
156 jars = append(jars, jar)
157 }
158
159 // Store the jars in the Contents property so that they can be used to add dependencies.
160 m.properties.Contents = jars
161 }
162}
163
Paul Duffin3451e162021-01-20 15:16:56 +0000164var BootImageInfoProvider = blueprint.NewProvider(BootImageInfo{})
165
166type BootImageInfo struct {
167 // The image config, internal to this module (and the dex_bootjars singleton).
Paul Duffina1d60252021-01-21 18:13:43 +0000168 //
169 // Will be nil if the BootImageInfo has not been provided for a specific module. That can occur
170 // when SkipDexpreoptBootJars(ctx) returns true.
Paul Duffin3451e162021-01-20 15:16:56 +0000171 imageConfig *bootImageConfig
172}
173
174func (i BootImageInfo) Modules() android.ConfiguredJarList {
175 return i.imageConfig.modules
176}
177
Paul Duffina1d60252021-01-21 18:13:43 +0000178// Get a map from ArchType to the associated boot image's contents for Android.
179//
180// Extension boot images only return their own files, not the files of the boot images they extend.
181func (i BootImageInfo) AndroidBootImageFilesByArchType() map[android.ArchType]android.OutputPaths {
182 files := map[android.ArchType]android.OutputPaths{}
183 if i.imageConfig != nil {
184 for _, variant := range i.imageConfig.variants {
185 // We also generate boot images for host (for testing), but we don't need those in the apex.
186 // TODO(b/177892522) - consider changing this to check Os.OsClass = android.Device
187 if variant.target.Os == android.Android {
188 files[variant.target.Arch.ArchType] = variant.imagesDeps
189 }
190 }
191 }
192 return files
193}
194
195func (b *BootImageModule) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
196 tag := ctx.OtherModuleDependencyTag(dep)
Paul Duffin65898052021-04-20 22:47:03 +0100197 if IsBootclasspathFragmentContentDepTag(tag) {
Paul Duffin4d101b62021-03-24 15:42:20 +0000198 // Boot image contents are automatically added to apex.
199 return true
Paul Duffinc7ef9892021-03-23 23:21:59 +0000200 }
Bob Badour07065cd2021-02-05 19:59:11 -0800201 if android.IsMetaDependencyTag(tag) {
202 // Cross-cutting metadata dependencies are metadata.
203 return false
204 }
Paul Duffina1d60252021-01-21 18:13:43 +0000205 panic(fmt.Errorf("boot_image module %q should not have a dependency on %q via tag %s", b, dep, android.PrettyPrintTag(tag)))
206}
207
208func (b *BootImageModule) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion android.ApiLevel) error {
209 return nil
210}
211
Paul Duffin65898052021-04-20 22:47:03 +0100212// ComponentDepsMutator adds dependencies onto modules before any prebuilt modules without a
213// corresponding source module are renamed. This means that adding a dependency using a name without
214// a prebuilt_ prefix will always resolve to a source module and when using a name with that prefix
215// it will always resolve to a prebuilt module.
216func (b *BootImageModule) ComponentDepsMutator(ctx android.BottomUpMutatorContext) {
217 module := ctx.Module()
218 _, isSourceModule := module.(*BootImageModule)
219
220 for _, name := range b.properties.Contents {
221 // A bootclasspath_fragment must depend only on other source modules, while the
222 // prebuilt_bootclasspath_fragment must only depend on other prebuilt modules.
Paul Duffina9dd6fa2021-04-22 17:25:57 +0100223 //
224 // TODO(b/177892522) - avoid special handling of jacocoagent.
225 if !isSourceModule && name != "jacocoagent" {
Paul Duffin65898052021-04-20 22:47:03 +0100226 name = android.PrebuiltNameFromSource(name)
227 }
228 ctx.AddDependency(module, bootclasspathFragmentContentDepTag, name)
229 }
230
231}
232
Paul Duffina1d60252021-01-21 18:13:43 +0000233func (b *BootImageModule) DepsMutator(ctx android.BottomUpMutatorContext) {
Paul Duffinc7ef9892021-03-23 23:21:59 +0000234
Paul Duffina1d60252021-01-21 18:13:43 +0000235 if SkipDexpreoptBootJars(ctx) {
236 return
237 }
238
239 // Add a dependency onto the dex2oat tool which is needed for creating the boot image. The
240 // path is retrieved from the dependency by GetGlobalSoongConfig(ctx).
241 dexpreopt.RegisterToolDeps(ctx)
242}
243
Paul Duffin3451e162021-01-20 15:16:56 +0000244func (b *BootImageModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
Paul Duffin9b381ef2021-04-08 23:01:37 +0100245 // Perform hidden API processing.
246 b.generateHiddenAPIBuildActions(ctx)
247
Paul Duffin3451e162021-01-20 15:16:56 +0000248 // Nothing to do if skipping the dexpreopt of boot image jars.
249 if SkipDexpreoptBootJars(ctx) {
250 return
251 }
252
Paul Duffina1d60252021-01-21 18:13:43 +0000253 // Force the GlobalSoongConfig to be created and cached for use by the dex_bootjars
254 // GenerateSingletonBuildActions method as it cannot create it for itself.
255 dexpreopt.GetGlobalSoongConfig(ctx)
256
Paul Duffin64be7bb2021-03-23 23:06:38 +0000257 imageConfig := b.getImageConfig(ctx)
Paul Duffin3451e162021-01-20 15:16:56 +0000258 if imageConfig == nil {
Paul Duffin3451e162021-01-20 15:16:56 +0000259 return
260 }
261
262 // Construct the boot image info from the config.
263 info := BootImageInfo{imageConfig: imageConfig}
264
265 // Make it available for other modules.
266 ctx.SetProvider(BootImageInfoProvider, info)
267}
Paul Duffinf7f65da2021-03-10 15:00:46 +0000268
Paul Duffin64be7bb2021-03-23 23:06:38 +0000269func (b *BootImageModule) getImageConfig(ctx android.EarlyModuleContext) *bootImageConfig {
270 // Get a map of the image configs that are supported.
271 imageConfigs := genBootImageConfigs(ctx)
272
273 // Retrieve the config for this image.
274 imageNamePtr := b.properties.Image_name
275 if imageNamePtr == nil {
276 return nil
277 }
278
279 imageName := *imageNamePtr
280 imageConfig := imageConfigs[imageName]
281 if imageConfig == nil {
282 ctx.PropertyErrorf("image_name", "Unknown image name %q, expected one of %s", imageName, strings.Join(android.SortedStringKeys(imageConfigs), ", "))
283 return nil
284 }
285 return imageConfig
286}
287
Paul Duffin9b381ef2021-04-08 23:01:37 +0100288// generateHiddenAPIBuildActions generates all the hidden API related build rules.
289func (b *BootImageModule) generateHiddenAPIBuildActions(ctx android.ModuleContext) {
290 // Resolve the properties to paths.
291 flagFileInfo := b.properties.Hidden_api.hiddenAPIFlagFileInfo(ctx)
292
293 // Store the information for use by platform_bootclasspath.
294 ctx.SetProvider(hiddenAPIFlagFileInfoProvider, flagFileInfo)
295}
296
Paul Duffinf7f65da2021-03-10 15:00:46 +0000297type bootImageMemberType struct {
298 android.SdkMemberTypeBase
299}
300
301func (b *bootImageMemberType) AddDependencies(mctx android.BottomUpMutatorContext, dependencyTag blueprint.DependencyTag, names []string) {
302 mctx.AddVariationDependencies(nil, dependencyTag, names...)
303}
304
305func (b *bootImageMemberType) IsInstance(module android.Module) bool {
306 _, ok := module.(*BootImageModule)
307 return ok
308}
309
310func (b *bootImageMemberType) AddPrebuiltModule(ctx android.SdkMemberContext, member android.SdkMember) android.BpModule {
Paul Duffin4b64ba02021-03-29 11:02:53 +0100311 if b.PropertyName == "boot_images" {
312 return ctx.SnapshotBuilder().AddPrebuiltModule(member, "prebuilt_boot_image")
313 } else {
314 return ctx.SnapshotBuilder().AddPrebuiltModule(member, "prebuilt_bootclasspath_fragment")
315 }
Paul Duffinf7f65da2021-03-10 15:00:46 +0000316}
317
318func (b *bootImageMemberType) CreateVariantPropertiesStruct() android.SdkMemberProperties {
319 return &bootImageSdkMemberProperties{}
320}
321
322type bootImageSdkMemberProperties struct {
323 android.SdkMemberPropertiesBase
324
Paul Duffina57835e2021-04-19 13:23:06 +0100325 // The image name
Paul Duffin64be7bb2021-03-23 23:06:38 +0000326 Image_name *string
Paul Duffina57835e2021-04-19 13:23:06 +0100327
328 // Contents of the bootclasspath fragment
329 Contents []string
Paul Duffin7c955552021-04-19 13:23:53 +0100330
331 // Flag files by *hiddenAPIFlagFileCategory
332 Flag_files_by_category map[*hiddenAPIFlagFileCategory]android.Paths
Paul Duffinf7f65da2021-03-10 15:00:46 +0000333}
334
335func (b *bootImageSdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) {
336 module := variant.(*BootImageModule)
337
338 b.Image_name = module.properties.Image_name
Paul Duffina57835e2021-04-19 13:23:06 +0100339 if b.Image_name == nil {
340 // Only one of image_name or contents can be specified. However, if image_name is set then the
341 // contents property is updated to match the configuration used to create the corresponding
342 // boot image. Therefore, contents property is only copied if the image name is not specified.
343 b.Contents = module.properties.Contents
344 }
Paul Duffin7c955552021-04-19 13:23:53 +0100345
346 // Get the flag file information from the module.
347 mctx := ctx.SdkModuleContext()
348 flagFileInfo := mctx.OtherModuleProvider(module, hiddenAPIFlagFileInfoProvider).(hiddenAPIFlagFileInfo)
349 b.Flag_files_by_category = flagFileInfo.categoryToPaths
Paul Duffinf7f65da2021-03-10 15:00:46 +0000350}
351
352func (b *bootImageSdkMemberProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) {
Paul Duffin64be7bb2021-03-23 23:06:38 +0000353 if b.Image_name != nil {
354 propertySet.AddProperty("image_name", *b.Image_name)
Paul Duffinf7f65da2021-03-10 15:00:46 +0000355 }
Paul Duffina57835e2021-04-19 13:23:06 +0100356
357 if len(b.Contents) > 0 {
358 propertySet.AddPropertyWithTag("contents", b.Contents, ctx.SnapshotBuilder().SdkMemberReferencePropertyTag(true))
359 }
Paul Duffin7c955552021-04-19 13:23:53 +0100360
361 builder := ctx.SnapshotBuilder()
362 if b.Flag_files_by_category != nil {
363 hiddenAPISet := propertySet.AddPropertySet("hidden_api")
364 for _, category := range hiddenAPIFlagFileCategories {
365 paths := b.Flag_files_by_category[category]
366 if len(paths) > 0 {
367 dests := []string{}
368 for _, p := range paths {
369 dest := filepath.Join("hiddenapi", p.Base())
370 builder.CopyToSnapshot(p, dest)
371 dests = append(dests, dest)
372 }
373 hiddenAPISet.AddProperty(category.propertyName, dests)
374 }
375 }
376 }
Paul Duffinf7f65da2021-03-10 15:00:46 +0000377}
378
379var _ android.SdkMemberType = (*bootImageMemberType)(nil)
380
381// A prebuilt version of the boot image module.
382//
383// At the moment this is basically just a boot image module that can be used as a prebuilt.
384// Eventually as more functionality is migrated into the boot image module from the singleton then
385// this will diverge.
386type prebuiltBootImageModule struct {
387 BootImageModule
388 prebuilt android.Prebuilt
389}
390
391func (module *prebuiltBootImageModule) Prebuilt() *android.Prebuilt {
392 return &module.prebuilt
393}
394
395func (module *prebuiltBootImageModule) Name() string {
396 return module.prebuilt.Name(module.ModuleBase.Name())
397}
398
399func prebuiltBootImageFactory() android.Module {
400 m := &prebuiltBootImageModule{}
401 m.AddProperties(&m.properties)
Paul Duffinf7f65da2021-03-10 15:00:46 +0000402 // This doesn't actually have any prebuilt files of its own so pass a placeholder for the srcs
403 // array.
404 android.InitPrebuiltModule(m, &[]string{"placeholder"})
405 android.InitApexModule(m)
406 android.InitSdkAwareModule(m)
Martin Stjernholmb79c7f12021-03-17 00:26:25 +0000407 android.InitAndroidArchModule(m, android.HostAndDeviceSupported, android.MultilibCommon)
Paul Duffinc7ef9892021-03-23 23:21:59 +0000408
409 // Perform some consistency checking to ensure that the configuration is correct.
410 android.AddLoadHook(m, func(ctx android.LoadHookContext) {
411 bootImageConsistencyCheck(ctx, &m.BootImageModule)
412 })
Paul Duffinf7f65da2021-03-10 15:00:46 +0000413 return m
414}