blob: 98fb417d06347593fda81a84e7df9a503d7eb6f6 [file] [log] [blame]
Paul Duffinb67d8782021-04-22 11:49:41 +01001// Copyright 2021 Google Inc. All rights reserved.
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 (
Colin Crossd6495802025-01-14 15:50:48 -080018 "fmt"
19
Paul Duffinb67d8782021-04-22 11:49:41 +010020 "android/soong/android"
Paul Duffin81667c82021-04-26 13:55:36 +010021
Paul Duffinb67d8782021-04-22 11:49:41 +010022 "github.com/google/blueprint"
23 "github.com/google/blueprint/proptools"
24)
25
26// Contains code that is common to both platform_bootclasspath and bootclasspath_fragment.
27
Paul Duffinb67d8782021-04-22 11:49:41 +010028// addDependencyOntoApexVariants adds dependencies onto the appropriate apex specific variants of
29// the module as specified in the ApexVariantReference list.
Colin Crossd8d8b852024-12-20 16:32:37 -080030func addDependencyOntoApexVariants(ctx android.BottomUpMutatorContext, propertyName string, refs []ApexVariantReference, tagType bootclasspathDependencyTagType) {
Paul Duffinb67d8782021-04-22 11:49:41 +010031 for i, ref := range refs {
32 apex := proptools.StringDefault(ref.Apex, "platform")
33
34 if ref.Module == nil {
35 ctx.PropertyErrorf(propertyName, "missing module name at position %d", i)
36 continue
37 }
38 name := proptools.String(ref.Module)
39
Colin Crossd8d8b852024-12-20 16:32:37 -080040 addDependencyOntoApexModulePair(ctx, apex, name, tagType)
Paul Duffinb67d8782021-04-22 11:49:41 +010041 }
42}
43
44// addDependencyOntoApexModulePair adds a dependency onto the specified APEX specific variant or the
45// specified module.
46//
Paul Duffin110b0ad2021-04-27 14:36:08 +010047// If apex="platform" or "system_ext" then this adds a dependency onto the platform variant of the
48// module. This adds dependencies onto the prebuilt and source modules with the specified name,
49// depending on which ones are available. Visiting must use isActiveModule to select the preferred
50// module when both source and prebuilt modules are available.
Paul Duffin9bacf562021-04-28 21:16:02 +010051//
52// Use gatherApexModulePairDepsWithTag to retrieve the dependencies.
Colin Crossd8d8b852024-12-20 16:32:37 -080053func addDependencyOntoApexModulePair(ctx android.BottomUpMutatorContext, apex string, name string, tagType bootclasspathDependencyTagType) {
54 tag := bootclasspathDependencyTag{
55 typ: tagType,
56 }
Colin Crossd6495802025-01-14 15:50:48 -080057 target := ctx.Module().Target()
58 if android.IsConfiguredJarForPlatform(apex) {
59 // Platform variant, add a direct dependency.
60 ctx.AddFarVariationDependencies(target.Variations(), tag, name)
61 } else {
62 // A module in an apex. Dependencies can't be added directly onto an apex variation, as that would
63 // require constructing a full ApexInfo configuration, which can't be predicted here. Add a dependency
64 // on the apex instead, and annotate the dependency tag with the desired module in the apex.
65 tag.moduleInApex = name
66 ctx.AddFarVariationDependencies(target.Variations(), tag, apex)
Paul Duffinb67d8782021-04-22 11:49:41 +010067 }
68
Paul Duffinb67d8782021-04-22 11:49:41 +010069}
70
Colin Cross92b0eb12025-02-06 11:49:52 -080071// gatherFragments collects fragments that are direct dependencies of this module, as well as
72// any fragments in apexes via the dependency on the apex. It returns a list of the fragment
73// modules and map from apex name to the fragment in that apex.
74func gatherFragments(ctx android.BaseModuleContext) ([]android.Module, map[string]android.Module) {
75 var fragments []android.Module
76
77 type fragmentInApex struct {
78 module string
79 apex string
80 }
81
82 var fragmentsInApexes []fragmentInApex
83
84 // Find any direct dependencies, as well as a list of the modules in apexes.
85 ctx.VisitDirectDeps(func(module android.Module) {
86 t := ctx.OtherModuleDependencyTag(module)
87 if bcpTag, ok := t.(bootclasspathDependencyTag); ok && bcpTag.typ == fragment {
88 if bcpTag.moduleInApex != "" {
89 fragmentsInApexes = append(fragmentsInApexes, fragmentInApex{bcpTag.moduleInApex, ctx.OtherModuleName(module)})
90 } else {
91 fragments = append(fragments, module)
92 }
93 }
94 })
95
96 fragmentsMap := make(map[string]android.Module)
97 for _, fragmentInApex := range fragmentsInApexes {
98 var found android.Module
99 // Find a desired module in an apex.
100 ctx.WalkDeps(func(child, parent android.Module) bool {
101 t := ctx.OtherModuleDependencyTag(child)
102 if parent == ctx.Module() {
103 if bcpTag, ok := t.(bootclasspathDependencyTag); ok && bcpTag.typ == fragment && ctx.OtherModuleName(child) == fragmentInApex.apex {
104 // This is the dependency from this module to the apex, recurse into it.
105 return true
106 }
107 } else if android.IsDontReplaceSourceWithPrebuiltTag(t) {
108 return false
109 } else if t == android.PrebuiltDepTag {
110 return false
111 } else if IsBootclasspathFragmentContentDepTag(t) {
112 return false
113 } else if android.RemoveOptionalPrebuiltPrefix(ctx.OtherModuleName(child)) == fragmentInApex.module {
114 // This is the desired module inside the apex.
115 if found != nil && child != found {
116 panic(fmt.Errorf("found two conflicting modules %q in apex %q: %s and %s",
117 fragmentInApex.module, fragmentInApex.apex, found, child))
118 }
119 found = child
120 }
121 return false
122 })
123 if found != nil {
124 if existing, exists := fragmentsMap[fragmentInApex.apex]; exists {
125 ctx.ModuleErrorf("apex %s has multiple fragments, %s and %s", fragmentInApex.apex, fragmentInApex.module, existing)
126 } else {
127 fragmentsMap[fragmentInApex.apex] = found
128 fragments = append(fragments, found)
129 }
130 } else if !ctx.Config().AllowMissingDependencies() {
131 ctx.ModuleErrorf("failed to find fragment %q in apex %q\n",
132 fragmentInApex.module, fragmentInApex.apex)
133 }
134 }
135 return fragments, fragmentsMap
136}
137
Paul Duffin9bacf562021-04-28 21:16:02 +0100138// gatherApexModulePairDepsWithTag returns the list of dependencies with the supplied tag that was
139// added by addDependencyOntoApexModulePair.
Colin Cross92b0eb12025-02-06 11:49:52 -0800140func gatherApexModulePairDepsWithTag(ctx android.BaseModuleContext, tagType bootclasspathDependencyTagType) ([]android.Module, map[android.Module]string) {
Paul Duffin9bacf562021-04-28 21:16:02 +0100141 var modules []android.Module
Colin Cross92b0eb12025-02-06 11:49:52 -0800142 modulesToApex := make(map[android.Module]string)
Colin Crossd6495802025-01-14 15:50:48 -0800143
144 type moduleInApex struct {
145 module string
146 apex string
147 }
148
149 var modulesInApexes []moduleInApex
150
Colin Crossd8d8b852024-12-20 16:32:37 -0800151 ctx.VisitDirectDeps(func(module android.Module) {
Paul Duffin9bacf562021-04-28 21:16:02 +0100152 t := ctx.OtherModuleDependencyTag(module)
Colin Crossd8d8b852024-12-20 16:32:37 -0800153 if bcpTag, ok := t.(bootclasspathDependencyTag); ok && bcpTag.typ == tagType {
Colin Crossd6495802025-01-14 15:50:48 -0800154 if bcpTag.moduleInApex != "" {
155 modulesInApexes = append(modulesInApexes, moduleInApex{bcpTag.moduleInApex, ctx.OtherModuleName(module)})
156 } else {
157 modules = append(modules, module)
158 }
Paul Duffin9bacf562021-04-28 21:16:02 +0100159 }
160 })
Colin Crossd6495802025-01-14 15:50:48 -0800161
162 for _, moduleInApex := range modulesInApexes {
163 var found android.Module
164 ctx.WalkDeps(func(child, parent android.Module) bool {
165 t := ctx.OtherModuleDependencyTag(child)
166 if parent == ctx.Module() {
167 if bcpTag, ok := t.(bootclasspathDependencyTag); ok && bcpTag.typ == tagType && ctx.OtherModuleName(child) == moduleInApex.apex {
168 // recurse into the apex
169 return true
170 }
171 } else if tagType != fragment && android.IsFragmentInApexTag(t) {
172 return true
173 } else if android.IsDontReplaceSourceWithPrebuiltTag(t) {
174 return false
175 } else if t == android.PrebuiltDepTag {
176 return false
177 } else if IsBootclasspathFragmentContentDepTag(t) {
178 return false
179 } else if android.RemoveOptionalPrebuiltPrefix(ctx.OtherModuleName(child)) == moduleInApex.module {
180 if found != nil && child != found {
181 panic(fmt.Errorf("found two conflicting modules %q in apex %q: %s and %s",
182 moduleInApex.module, moduleInApex.apex, found, child))
183 }
184 found = child
185 }
186 return false
187 })
188 if found != nil {
189 modules = append(modules, found)
Colin Cross92b0eb12025-02-06 11:49:52 -0800190 if existing, exists := modulesToApex[found]; exists && existing != moduleInApex.apex {
191 ctx.ModuleErrorf("module %s is in two apexes, %s and %s", moduleInApex.module, existing, moduleInApex.apex)
192 } else {
193 modulesToApex[found] = moduleInApex.apex
194 }
Colin Crossd6495802025-01-14 15:50:48 -0800195 } else if !ctx.Config().AllowMissingDependencies() {
196 ctx.ModuleErrorf("failed to find module %q in apex %q\n",
197 moduleInApex.module, moduleInApex.apex)
198 }
199 }
Colin Cross92b0eb12025-02-06 11:49:52 -0800200 return modules, modulesToApex
Paul Duffin9bacf562021-04-28 21:16:02 +0100201}
202
Paul Duffinb67d8782021-04-22 11:49:41 +0100203// ApexVariantReference specifies a particular apex variant of a module.
204type ApexVariantReference struct {
Paul Duffin51227d82021-05-18 12:54:27 +0100205 android.BpPrintableBase
206
Paul Duffinb67d8782021-04-22 11:49:41 +0100207 // The name of the module apex variant, i.e. the apex containing the module variant.
208 //
209 // If this is not specified then it defaults to "platform" which will cause a dependency to be
210 // added to the module's platform variant.
Paul Duffin110b0ad2021-04-27 14:36:08 +0100211 //
212 // A value of system_ext should be used for any module that will be part of the system_ext
213 // partition.
Paul Duffinb67d8782021-04-22 11:49:41 +0100214 Apex *string
215
216 // The name of the module.
217 Module *string
218}
219
220// BootclasspathFragmentsDepsProperties contains properties related to dependencies onto fragments.
221type BootclasspathFragmentsDepsProperties struct {
222 // The names of the bootclasspath_fragment modules that form part of this module.
223 Fragments []ApexVariantReference
224}
225
226// addDependenciesOntoFragments adds dependencies to the fragments specified in this properties
227// structure.
228func (p *BootclasspathFragmentsDepsProperties) addDependenciesOntoFragments(ctx android.BottomUpMutatorContext) {
Colin Crossd8d8b852024-12-20 16:32:37 -0800229 addDependencyOntoApexVariants(ctx, "fragments", p.Fragments, fragment)
Paul Duffinb67d8782021-04-22 11:49:41 +0100230}
231
232// bootclasspathDependencyTag defines dependencies from/to bootclasspath_fragment,
233// prebuilt_bootclasspath_fragment and platform_bootclasspath onto either source or prebuilt
234// modules.
235type bootclasspathDependencyTag struct {
236 blueprint.BaseDependencyTag
237
Colin Crossd8d8b852024-12-20 16:32:37 -0800238 typ bootclasspathDependencyTagType
239
Colin Crossd6495802025-01-14 15:50:48 -0800240 // moduleInApex is set to the name of the desired module when this dependency points
241 // to the apex that the modules is contained in.
242 moduleInApex string
Paul Duffinb67d8782021-04-22 11:49:41 +0100243}
244
Colin Crossd8d8b852024-12-20 16:32:37 -0800245type bootclasspathDependencyTagType int
246
247const (
248 // The tag used for dependencies onto bootclasspath_fragments.
249 fragment bootclasspathDependencyTagType = iota
250 // The tag used for dependencies onto platform_bootclasspath.
251 platform
252 dexpreoptBootJar
253 artBootJar
254 platformBootJar
255 apexBootJar
256)
257
Paul Duffinb67d8782021-04-22 11:49:41 +0100258func (t bootclasspathDependencyTag) ExcludeFromVisibilityEnforcement() {
259}
260
Colin Crossd6495802025-01-14 15:50:48 -0800261func (t bootclasspathDependencyTag) LicenseAnnotations() []android.LicenseAnnotation {
262 return []android.LicenseAnnotation{android.LicenseAnnotationSharedDependency}
Colin Crossd8d8b852024-12-20 16:32:37 -0800263}
264
Paul Duffinb67d8782021-04-22 11:49:41 +0100265// Dependencies that use the bootclasspathDependencyTag instances are only added after all the
266// visibility checking has been done so this has no functional effect. However, it does make it
267// clear that visibility is not being enforced on these tags.
268var _ android.ExcludeFromVisibilityEnforcementTag = bootclasspathDependencyTag{}
269
Paul Duffin10931582021-04-25 10:13:54 +0100270// BootclasspathNestedAPIProperties defines properties related to the API provided by parts of the
271// bootclasspath that are nested within the main BootclasspathAPIProperties.
272type BootclasspathNestedAPIProperties struct {
273 // java_library or preferably, java_sdk_library modules providing stub classes that define the
274 // APIs provided by this bootclasspath_fragment.
Cole Faustaaff7822024-07-30 12:59:44 -0700275 Stub_libs proptools.Configurable[[]string]
Paul Duffin10931582021-04-25 10:13:54 +0100276}
277
278// BootclasspathAPIProperties defines properties for defining the API provided by parts of the
279// bootclasspath.
280type BootclasspathAPIProperties struct {
281 // Api properties provide information about the APIs provided by the bootclasspath_fragment.
282 // Properties in this section apply to public, system and test api scopes. They DO NOT apply to
283 // core_platform as that is a special, ART specific scope, that does not follow the pattern and so
284 // has its own section. It is in the process of being deprecated and replaced by the system scope
285 // but this will remain for the foreseeable future to maintain backwards compatibility.
286 //
287 // Every bootclasspath_fragment must specify at least one stubs_lib in this section and must
288 // specify stubs for all the APIs provided by its contents. Failure to do so will lead to those
289 // methods being inaccessible to other parts of Android, including but not limited to
290 // applications.
291 Api BootclasspathNestedAPIProperties
292
293 // Properties related to the core platform API surface.
294 //
295 // This must only be used by the following modules:
296 // * ART
297 // * Conscrypt
298 // * I18N
299 //
300 // The bootclasspath_fragments for each of the above modules must specify at least one stubs_lib
301 // and must specify stubs for all the APIs provided by its contents. Failure to do so will lead to
302 // those methods being inaccessible to the other modules in the list.
303 Core_platform_api BootclasspathNestedAPIProperties
304}
305
Paul Duffin31fad802021-06-18 18:14:25 +0100306// apiScopeToStubLibs calculates the stub library modules for each relevant *HiddenAPIScope from the
Paul Duffin10931582021-04-25 10:13:54 +0100307// Stub_libs properties.
Cole Faustaaff7822024-07-30 12:59:44 -0700308func (p BootclasspathAPIProperties) apiScopeToStubLibs(ctx android.BaseModuleContext) map[*HiddenAPIScope][]string {
Paul Duffin31fad802021-06-18 18:14:25 +0100309 m := map[*HiddenAPIScope][]string{}
310 for _, apiScope := range hiddenAPISdkLibrarySupportedScopes {
Cole Faustaaff7822024-07-30 12:59:44 -0700311 m[apiScope] = p.Api.Stub_libs.GetOrDefault(ctx, nil)
Paul Duffin10931582021-04-25 10:13:54 +0100312 }
Cole Faustaaff7822024-07-30 12:59:44 -0700313 m[CorePlatformHiddenAPIScope] = p.Core_platform_api.Stub_libs.GetOrDefault(ctx, nil)
Paul Duffin10931582021-04-25 10:13:54 +0100314 return m
315}