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