• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// 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 (
18	"fmt"
19
20	"android/soong/android"
21
22	"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
28// addDependencyOntoApexVariants adds dependencies onto the appropriate apex specific variants of
29// the module as specified in the ApexVariantReference list.
30func addDependencyOntoApexVariants(ctx android.BottomUpMutatorContext, propertyName string, refs []ApexVariantReference, tagType bootclasspathDependencyTagType) {
31	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
40		addDependencyOntoApexModulePair(ctx, apex, name, tagType)
41	}
42}
43
44// addDependencyOntoApexModulePair adds a dependency onto the specified APEX specific variant or the
45// specified module.
46//
47// 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.
51//
52// Use gatherApexModulePairDepsWithTag to retrieve the dependencies.
53func addDependencyOntoApexModulePair(ctx android.BottomUpMutatorContext, apex string, name string, tagType bootclasspathDependencyTagType) {
54	tag := bootclasspathDependencyTag{
55		typ: tagType,
56	}
57	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)
67	}
68
69}
70
71// 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
138// gatherApexModulePairDepsWithTag returns the list of dependencies with the supplied tag that was
139// added by addDependencyOntoApexModulePair.
140func gatherApexModulePairDepsWithTag(ctx android.BaseModuleContext, tagType bootclasspathDependencyTagType) ([]android.Module, map[android.Module]string) {
141	var modules []android.Module
142	modulesToApex := make(map[android.Module]string)
143
144	type moduleInApex struct {
145		module string
146		apex   string
147	}
148
149	var modulesInApexes []moduleInApex
150
151	ctx.VisitDirectDeps(func(module android.Module) {
152		t := ctx.OtherModuleDependencyTag(module)
153		if bcpTag, ok := t.(bootclasspathDependencyTag); ok && bcpTag.typ == tagType {
154			if bcpTag.moduleInApex != "" {
155				modulesInApexes = append(modulesInApexes, moduleInApex{bcpTag.moduleInApex, ctx.OtherModuleName(module)})
156			} else {
157				modules = append(modules, module)
158			}
159		}
160	})
161
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)
190			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			}
195		} else if !ctx.Config().AllowMissingDependencies() {
196			ctx.ModuleErrorf("failed to find module %q in apex %q\n",
197				moduleInApex.module, moduleInApex.apex)
198		}
199	}
200	return modules, modulesToApex
201}
202
203// ApexVariantReference specifies a particular apex variant of a module.
204type ApexVariantReference struct {
205	android.BpPrintableBase
206
207	// 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.
211	//
212	// A value of system_ext should be used for any module that will be part of the system_ext
213	// partition.
214	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) {
229	addDependencyOntoApexVariants(ctx, "fragments", p.Fragments, fragment)
230}
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
238	typ bootclasspathDependencyTagType
239
240	// 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
243}
244
245type 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
258func (t bootclasspathDependencyTag) ExcludeFromVisibilityEnforcement() {
259}
260
261func (t bootclasspathDependencyTag) LicenseAnnotations() []android.LicenseAnnotation {
262	return []android.LicenseAnnotation{android.LicenseAnnotationSharedDependency}
263}
264
265// 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
270// 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.
275	Stub_libs proptools.Configurable[[]string]
276}
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
306// apiScopeToStubLibs calculates the stub library modules for each relevant *HiddenAPIScope from the
307// Stub_libs properties.
308func (p BootclasspathAPIProperties) apiScopeToStubLibs(ctx android.BaseModuleContext) map[*HiddenAPIScope][]string {
309	m := map[*HiddenAPIScope][]string{}
310	for _, apiScope := range hiddenAPISdkLibrarySupportedScopes {
311		m[apiScope] = p.Api.Stub_libs.GetOrDefault(ctx, nil)
312	}
313	m[CorePlatformHiddenAPIScope] = p.Core_platform_api.Stub_libs.GetOrDefault(ctx, nil)
314	return m
315}
316