1// Copyright 2020 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 android 16 17import ( 18 "fmt" 19 "path/filepath" 20 "reflect" 21 "strings" 22 "sync" 23 24 "github.com/google/blueprint" 25 "github.com/google/blueprint/gobtools" 26) 27 28// Adds cross-cutting licenses dependency to propagate license metadata through the build system. 29// 30// Stage 1 - bottom-up records package-level default_applicable_licenses property mapped by package name. 31// Stage 2 - bottom-up converts licenses property or package default_applicable_licenses to dependencies. 32// Stage 3 - bottom-up type-checks every added applicable license dependency and license_kind dependency. 33// Stage 4 - GenerateBuildActions calculates properties for the union of license kinds, conditions and texts. 34 35type licensesDependencyTag struct { 36 blueprint.BaseDependencyTag 37} 38 39func (l licensesDependencyTag) SdkMemberType(Module) SdkMemberType { 40 // Add the supplied module to the sdk as a license module. 41 return LicenseModuleSdkMemberType 42} 43 44func (l licensesDependencyTag) ExportMember() bool { 45 // The license module will only every be referenced from within the sdk. This will ensure that it 46 // gets a unique name and so avoid clashing with the original license module. 47 return false 48} 49 50var ( 51 licensesTag = licensesDependencyTag{} 52 53 // License modules, i.e. modules depended upon via a licensesTag, must be automatically added to 54 // any sdk/module_exports to which their referencing module is a member. 55 _ SdkMemberDependencyTag = licensesTag 56) 57 58// Describes the property provided by a module to reference applicable licenses. 59type applicableLicensesProperty interface { 60 // The name of the property. e.g. default_applicable_licenses or licenses 61 getName() string 62 // The values assigned to the property. (Must reference license modules.) 63 getStrings() []string 64} 65 66type applicableLicensesPropertyImpl struct { 67 name string 68 licensesProperty *[]string 69} 70 71type applicableLicensesPropertyImplGob struct { 72 Name string 73 LicensesProperty []string 74} 75 76func (a *applicableLicensesPropertyImpl) ToGob() *applicableLicensesPropertyImplGob { 77 return &applicableLicensesPropertyImplGob{ 78 Name: a.name, 79 LicensesProperty: *a.licensesProperty, 80 } 81} 82 83func (a *applicableLicensesPropertyImpl) FromGob(data *applicableLicensesPropertyImplGob) { 84 a.name = data.Name 85 a.licensesProperty = &data.LicensesProperty 86} 87 88func (a applicableLicensesPropertyImpl) GobEncode() ([]byte, error) { 89 return gobtools.CustomGobEncode[applicableLicensesPropertyImplGob](&a) 90} 91 92func (a *applicableLicensesPropertyImpl) GobDecode(data []byte) error { 93 return gobtools.CustomGobDecode[applicableLicensesPropertyImplGob](data, a) 94} 95 96func newApplicableLicensesProperty(name string, licensesProperty *[]string) applicableLicensesProperty { 97 return applicableLicensesPropertyImpl{ 98 name: name, 99 licensesProperty: licensesProperty, 100 } 101} 102 103func (p applicableLicensesPropertyImpl) getName() string { 104 return p.name 105} 106 107func (p applicableLicensesPropertyImpl) getStrings() []string { 108 return *p.licensesProperty 109} 110 111// Set the primary applicable licenses property for a module. 112func setPrimaryLicensesProperty(module Module, name string, licensesProperty *[]string) { 113 module.base().primaryLicensesProperty = newApplicableLicensesProperty(name, licensesProperty) 114} 115 116// Storage blob for a package's default_applicable_licenses mapped by package directory. 117type licensesContainer struct { 118 licenses []string 119} 120 121func (r licensesContainer) getLicenses() []string { 122 return r.licenses 123} 124 125var packageDefaultLicensesMap = NewOnceKey("packageDefaultLicensesMap") 126 127// The map from package dir name to default applicable licenses as a licensesContainer. 128func moduleToPackageDefaultLicensesMap(config Config) *sync.Map { 129 return config.Once(packageDefaultLicensesMap, func() interface{} { 130 return &sync.Map{} 131 }).(*sync.Map) 132} 133 134// Registers the function that maps each package to its default_applicable_licenses. 135// 136// This goes before defaults expansion so the defaults can pick up the package default. 137func RegisterLicensesPackageMapper(ctx RegisterMutatorsContext) { 138 ctx.BottomUp("licensesPackageMapper", licensesPackageMapper) 139} 140 141// Registers the function that gathers the license dependencies for each module. 142// 143// This goes after defaults expansion so that it can pick up default licenses and before visibility enforcement. 144func RegisterLicensesPropertyGatherer(ctx RegisterMutatorsContext) { 145 ctx.BottomUp("licensesPropertyGatherer", licensesPropertyGatherer) 146} 147 148// Registers the function that verifies the licenses and license_kinds dependency types for each module. 149func RegisterLicensesDependencyChecker(ctx RegisterMutatorsContext) { 150 ctx.BottomUp("licensesPropertyChecker", licensesDependencyChecker) 151} 152 153// Maps each package to its default applicable licenses. 154func licensesPackageMapper(ctx BottomUpMutatorContext) { 155 p, ok := ctx.Module().(*packageModule) 156 if !ok { 157 return 158 } 159 160 licenses := getLicenses(ctx, p) 161 162 dir := ctx.ModuleDir() 163 c := makeLicensesContainer(licenses) 164 moduleToPackageDefaultLicensesMap(ctx.Config()).Store(dir, c) 165} 166 167// Copies the default_applicable_licenses property values for mapping by package directory. 168func makeLicensesContainer(propVals []string) licensesContainer { 169 licenses := make([]string, 0, len(propVals)) 170 licenses = append(licenses, propVals...) 171 172 return licensesContainer{licenses} 173} 174 175// Gathers the applicable licenses into dependency references after defaults expansion. 176func licensesPropertyGatherer(ctx BottomUpMutatorContext) { 177 m, ok := ctx.Module().(Module) 178 if !ok { 179 return 180 } 181 182 if exemptFromRequiredApplicableLicensesProperty(m) { 183 return 184 } 185 186 licenses := getLicenses(ctx, m) 187 188 var fullyQualifiedLicenseNames []string 189 for _, license := range licenses { 190 fullyQualifiedLicenseName := license 191 if !strings.HasPrefix(license, "//") { 192 licenseModuleDir := ctx.OtherModuleDir(m) 193 for licenseModuleDir != "." && !ctx.OtherModuleExists(fmt.Sprintf("//%s:%s", licenseModuleDir, license)) { 194 licenseModuleDir = filepath.Dir(licenseModuleDir) 195 } 196 if licenseModuleDir == "." { 197 fullyQualifiedLicenseName = license 198 } else { 199 fullyQualifiedLicenseName = fmt.Sprintf("//%s:%s", licenseModuleDir, license) 200 } 201 } 202 fullyQualifiedLicenseNames = append(fullyQualifiedLicenseNames, fullyQualifiedLicenseName) 203 } 204 205 ctx.AddVariationDependencies(nil, licensesTag, fullyQualifiedLicenseNames...) 206} 207 208// Verifies the license and license_kind dependencies are each the correct kind of module. 209func licensesDependencyChecker(ctx BottomUpMutatorContext) { 210 m, ok := ctx.Module().(Module) 211 if !ok { 212 return 213 } 214 215 // license modules have no licenses, but license_kinds must refer to license_kind modules 216 if _, ok := m.(*licenseModule); ok { 217 for _, module := range ctx.GetDirectDepsWithTag(licenseKindTag) { 218 if _, ok := module.(*licenseKindModule); !ok { 219 ctx.ModuleErrorf("license_kinds property %q is not a license_kind module", ctx.OtherModuleName(module)) 220 } 221 } 222 return 223 } 224 225 if exemptFromRequiredApplicableLicensesProperty(m) { 226 return 227 } 228 229 for _, module := range ctx.GetDirectDepsWithTag(licensesTag) { 230 if _, ok := module.(*licenseModule); !ok { 231 propertyName := "licenses" 232 primaryProperty := m.base().primaryLicensesProperty 233 if primaryProperty != nil { 234 propertyName = primaryProperty.getName() 235 } 236 ctx.ModuleErrorf("%s property %q is not a license module", propertyName, ctx.OtherModuleName(module)) 237 } 238 } 239} 240 241// Flattens license and license_kind dependencies into calculated properties. 242// 243// Re-validates applicable licenses properties refer only to license modules and license_kinds properties refer 244// only to license_kind modules. 245func licensesPropertyFlattener(ctx ModuleContext) { 246 m, ok := ctx.Module().(Module) 247 if !ok { 248 return 249 } 250 251 if exemptFromRequiredApplicableLicensesProperty(m) { 252 return 253 } 254 255 var licenses []string 256 var texts NamedPaths 257 var conditions []string 258 var kinds []string 259 for _, module := range ctx.GetDirectDepsProxyWithTag(licensesTag) { 260 if l, ok := OtherModuleProvider(ctx, module, LicenseInfoProvider); ok { 261 licenses = append(licenses, ctx.OtherModuleName(module)) 262 if m.base().commonProperties.Effective_package_name == nil && l.PackageName != nil { 263 m.base().commonProperties.Effective_package_name = l.PackageName 264 } 265 texts = append(texts, l.EffectiveLicenseText...) 266 kinds = append(kinds, l.EffectiveLicenseKinds...) 267 conditions = append(conditions, l.EffectiveLicenseConditions...) 268 } else { 269 propertyName := "licenses" 270 primaryProperty := m.base().primaryLicensesProperty 271 if primaryProperty != nil { 272 propertyName = primaryProperty.getName() 273 } 274 ctx.ModuleErrorf("%s property %q is not a license module", propertyName, ctx.OtherModuleName(module)) 275 } 276 } 277 278 m.base().commonProperties.Effective_license_text = SortedUniqueNamedPaths(texts) 279 m.base().commonProperties.Effective_license_kinds = SortedUniqueStrings(kinds) 280 m.base().commonProperties.Effective_license_conditions = SortedUniqueStrings(conditions) 281 282 // Make the license information available for other modules. 283 licenseInfo := LicensesInfo{ 284 Licenses: licenses, 285 } 286 SetProvider(ctx, LicensesInfoProvider, licenseInfo) 287} 288 289// Update a property NamedPath array with a distinct union of its values and a list of new values. 290func namePathProps(prop *NamedPaths, name *string, values ...Path) { 291 if name == nil { 292 for _, value := range values { 293 *prop = append(*prop, NamedPath{value, ""}) 294 } 295 } else { 296 for _, value := range values { 297 *prop = append(*prop, NamedPath{value, *name}) 298 } 299 } 300 *prop = SortedUniqueNamedPaths(*prop) 301} 302 303// Get the licenses property falling back to the package default. 304func getLicenses(ctx BaseModuleContext, module Module) []string { 305 if exemptFromRequiredApplicableLicensesProperty(module) { 306 return nil 307 } 308 309 primaryProperty := module.base().primaryLicensesProperty 310 if primaryProperty == nil { 311 if !ctx.Config().IsEnvFalse("ANDROID_REQUIRE_LICENSES") { 312 ctx.ModuleErrorf("module type %q must have an applicable licenses property", ctx.OtherModuleType(module)) 313 } 314 return nil 315 } 316 317 licenses := primaryProperty.getStrings() 318 if len(licenses) > 0 { 319 s := make(map[string]bool) 320 for _, l := range licenses { 321 if _, ok := s[l]; ok { 322 ctx.ModuleErrorf("duplicate %q %s", l, primaryProperty.getName()) 323 } 324 s[l] = true 325 } 326 return licenses 327 } 328 329 dir := ctx.OtherModuleDir(module) 330 331 moduleToApplicableLicenses := moduleToPackageDefaultLicensesMap(ctx.Config()) 332 value, ok := moduleToApplicableLicenses.Load(dir) 333 var c licensesContainer 334 if ok { 335 c = value.(licensesContainer) 336 } else { 337 c = licensesContainer{} 338 } 339 return c.getLicenses() 340} 341 342// Returns whether a module is an allowed list of modules that do not have or need applicable licenses. 343func exemptFromRequiredApplicableLicensesProperty(module Module) bool { 344 switch reflect.TypeOf(module).String() { 345 case "*android.licenseModule": // is a license, doesn't need one 346 case "*android.licenseKindModule": // is a license, doesn't need one 347 case "*android.genNoticeModule": // contains license texts as data 348 case "*android.NamespaceModule": // just partitions things, doesn't add anything 349 case "*android.soongConfigModuleTypeModule": // creates aliases for modules with licenses 350 case "*android.soongConfigModuleTypeImport": // creates aliases for modules with licenses 351 case "*android.soongConfigStringVariableDummyModule": // used for creating aliases 352 case "*android.soongConfigBoolVariableDummyModule": // used for creating aliases 353 default: 354 return false 355 } 356 return true 357} 358 359// LicensesInfo contains information about licenses for a specific module. 360type LicensesInfo struct { 361 // The list of license modules this depends upon, either explicitly or through default package 362 // configuration. 363 Licenses []string 364} 365 366var LicensesInfoProvider = blueprint.NewProvider[LicensesInfo]() 367 368func init() { 369 RegisterMakeVarsProvider(pctx, licensesMakeVarsProvider) 370} 371 372func licensesMakeVarsProvider(ctx MakeVarsContext) { 373 ctx.Strict("BUILD_LICENSE_METADATA", 374 ctx.Config().HostToolPath(ctx, "build_license_metadata").String()) 375 ctx.Strict("COPY_LICENSE_METADATA", 376 ctx.Config().HostToolPath(ctx, "copy_license_metadata").String()) 377 ctx.Strict("HTMLNOTICE", ctx.Config().HostToolPath(ctx, "htmlnotice").String()) 378 ctx.Strict("XMLNOTICE", ctx.Config().HostToolPath(ctx, "xmlnotice").String()) 379 ctx.Strict("TEXTNOTICE", ctx.Config().HostToolPath(ctx, "textnotice").String()) 380 ctx.Strict("COMPLIANCENOTICE_SHIPPEDLIBS", ctx.Config().HostToolPath(ctx, "compliancenotice_shippedlibs").String()) 381 ctx.Strict("COMPLIANCE_LISTSHARE", ctx.Config().HostToolPath(ctx, "compliance_listshare").String()) 382 ctx.Strict("COMPLIANCE_CHECKSHARE", ctx.Config().HostToolPath(ctx, "compliance_checkshare").String()) 383} 384