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