| Bob Badour | 37af046 | 2021-01-07 03:34:31 +0000 | [diff] [blame] | 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 |  | 
|  | 15 | package android | 
|  | 16 |  | 
|  | 17 | import ( | 
|  | 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 |  | 
|  | 31 | type licensesDependencyTag struct { | 
|  | 32 | blueprint.BaseDependencyTag | 
|  | 33 | } | 
|  | 34 |  | 
| Paul Duffin | b0bb376 | 2021-05-06 16:48:05 +0100 | [diff] [blame] | 35 | func (l licensesDependencyTag) SdkMemberType(Module) SdkMemberType { | 
|  | 36 | // Add the supplied module to the sdk as a license module. | 
|  | 37 | return LicenseModuleSdkMemberType | 
|  | 38 | } | 
|  | 39 |  | 
|  | 40 | func (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 |  | 
| Bob Badour | 37af046 | 2021-01-07 03:34:31 +0000 | [diff] [blame] | 46 | var ( | 
|  | 47 | licensesTag = licensesDependencyTag{} | 
| Paul Duffin | b0bb376 | 2021-05-06 16:48:05 +0100 | [diff] [blame] | 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. | 
| Paul Duffin | f7b3d0d | 2021-09-02 14:29:21 +0100 | [diff] [blame] | 51 | _ SdkMemberDependencyTag = licensesTag | 
| Bob Badour | 37af046 | 2021-01-07 03:34:31 +0000 | [diff] [blame] | 52 | ) | 
|  | 53 |  | 
|  | 54 | // Describes the property provided by a module to reference applicable licenses. | 
|  | 55 | type 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 |  | 
|  | 62 | type applicableLicensesPropertyImpl struct { | 
|  | 63 | name             string | 
|  | 64 | licensesProperty *[]string | 
|  | 65 | } | 
|  | 66 |  | 
|  | 67 | func newApplicableLicensesProperty(name string, licensesProperty *[]string) applicableLicensesProperty { | 
|  | 68 | return applicableLicensesPropertyImpl{ | 
| Paul Duffin | 3c298a3 | 2021-03-04 17:44:03 +0000 | [diff] [blame] | 69 | name:             name, | 
| Bob Badour | 37af046 | 2021-01-07 03:34:31 +0000 | [diff] [blame] | 70 | licensesProperty: licensesProperty, | 
|  | 71 | } | 
|  | 72 | } | 
|  | 73 |  | 
|  | 74 | func (p applicableLicensesPropertyImpl) getName() string { | 
|  | 75 | return p.name | 
|  | 76 | } | 
|  | 77 |  | 
|  | 78 | func (p applicableLicensesPropertyImpl) getStrings() []string { | 
|  | 79 | return *p.licensesProperty | 
|  | 80 | } | 
|  | 81 |  | 
|  | 82 | // Set the primary applicable licenses property for a module. | 
|  | 83 | func 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. | 
|  | 88 | type licensesContainer struct { | 
|  | 89 | licenses []string | 
|  | 90 | } | 
|  | 91 |  | 
|  | 92 | func (r licensesContainer) getLicenses() []string { | 
|  | 93 | return r.licenses | 
|  | 94 | } | 
|  | 95 |  | 
|  | 96 | var packageDefaultLicensesMap = NewOnceKey("packageDefaultLicensesMap") | 
|  | 97 |  | 
|  | 98 | // The map from package dir name to default applicable licenses as a licensesContainer. | 
|  | 99 | func 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. | 
|  | 108 | func 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. | 
|  | 115 | func 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. | 
|  | 120 | func RegisterLicensesDependencyChecker(ctx RegisterMutatorsContext) { | 
|  | 121 | ctx.BottomUp("licensesPropertyChecker", licensesDependencyChecker).Parallel() | 
|  | 122 | } | 
|  | 123 |  | 
|  | 124 | // Maps each package to its default applicable licenses. | 
|  | 125 | func 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. | 
|  | 139 | func 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. | 
|  | 147 | func 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) | 
| Bob Badour | 37af046 | 2021-01-07 03:34:31 +0000 | [diff] [blame] | 158 | ctx.AddVariationDependencies(nil, licensesTag, licenses...) | 
|  | 159 | } | 
|  | 160 |  | 
|  | 161 | // Verifies the license and license_kind dependencies are each the correct kind of module. | 
|  | 162 | func 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. | 
|  | 198 | func licensesPropertyFlattener(ctx ModuleContext) { | 
|  | 199 | m, ok := ctx.Module().(Module) | 
|  | 200 | if !ok { | 
|  | 201 | return | 
|  | 202 | } | 
|  | 203 |  | 
| Bob Badour | 37af046 | 2021-01-07 03:34:31 +0000 | [diff] [blame] | 204 | if exemptFromRequiredApplicableLicensesProperty(m) { | 
|  | 205 | return | 
|  | 206 | } | 
|  | 207 |  | 
| Paul Duffin | b0bb376 | 2021-05-06 16:48:05 +0100 | [diff] [blame] | 208 | var licenses []string | 
| Bob Badour | 37af046 | 2021-01-07 03:34:31 +0000 | [diff] [blame] | 209 | for _, module := range ctx.GetDirectDepsWithTag(licensesTag) { | 
|  | 210 | if l, ok := module.(*licenseModule); ok { | 
| Paul Duffin | b0bb376 | 2021-05-06 16:48:05 +0100 | [diff] [blame] | 211 | licenses = append(licenses, ctx.OtherModuleName(module)) | 
| Bob Badour | 37af046 | 2021-01-07 03:34:31 +0000 | [diff] [blame] | 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 | } | 
| Paul Duffin | ec0836a | 2021-05-10 22:53:30 +0100 | [diff] [blame] | 215 | mergeStringProps(&m.base().commonProperties.Effective_licenses, module.base().commonProperties.Effective_licenses...) | 
| Bob Badour | 4101c71 | 2022-02-09 11:54:35 -0800 | [diff] [blame] | 216 | mergeNamedPathProps(&m.base().commonProperties.Effective_license_text, module.base().commonProperties.Effective_license_text...) | 
| Paul Duffin | ec0836a | 2021-05-10 22:53:30 +0100 | [diff] [blame] | 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...) | 
| Bob Badour | 37af046 | 2021-01-07 03:34:31 +0000 | [diff] [blame] | 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 | } | 
| Paul Duffin | b0bb376 | 2021-05-06 16:48:05 +0100 | [diff] [blame] | 228 |  | 
|  | 229 | // Make the license information available for other modules. | 
|  | 230 | licenseInfo := LicenseInfo{ | 
|  | 231 | Licenses: licenses, | 
|  | 232 | } | 
| Colin Cross | 4021302 | 2023-12-13 15:19:49 -0800 | [diff] [blame] | 233 | SetProvider(ctx, LicenseInfoProvider, licenseInfo) | 
| Bob Badour | 37af046 | 2021-01-07 03:34:31 +0000 | [diff] [blame] | 234 | } | 
|  | 235 |  | 
|  | 236 | // Update a property string array with a distinct union of its values and a list of new values. | 
| Paul Duffin | ec0836a | 2021-05-10 22:53:30 +0100 | [diff] [blame] | 237 | func mergeStringProps(prop *[]string, values ...string) { | 
|  | 238 | *prop = append(*prop, values...) | 
|  | 239 | *prop = SortedUniqueStrings(*prop) | 
|  | 240 | } | 
|  | 241 |  | 
| Bob Badour | 4101c71 | 2022-02-09 11:54:35 -0800 | [diff] [blame] | 242 | // Update a property NamedPath array with a distinct union of its values and a list of new values. | 
|  | 243 | func 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. | 
|  | 257 | func mergeNamedPathProps(prop *NamedPaths, values ...NamedPath) { | 
| Paul Duffin | ec0836a | 2021-05-10 22:53:30 +0100 | [diff] [blame] | 258 | *prop = append(*prop, values...) | 
| Bob Badour | 4101c71 | 2022-02-09 11:54:35 -0800 | [diff] [blame] | 259 | *prop = SortedUniqueNamedPaths(*prop) | 
| Bob Badour | 37af046 | 2021-01-07 03:34:31 +0000 | [diff] [blame] | 260 | } | 
|  | 261 |  | 
|  | 262 | // Get the licenses property falling back to the package default. | 
|  | 263 | func getLicenses(ctx BaseModuleContext, module Module) []string { | 
|  | 264 | if exemptFromRequiredApplicableLicensesProperty(module) { | 
|  | 265 | return nil | 
|  | 266 | } | 
|  | 267 |  | 
|  | 268 | primaryProperty := module.base().primaryLicensesProperty | 
|  | 269 | if primaryProperty == nil { | 
| Bob Badour | 65ee90a | 2021-09-02 15:33:10 -0700 | [diff] [blame] | 270 | if !ctx.Config().IsEnvFalse("ANDROID_REQUIRE_LICENSES") { | 
| Bob Badour | 37af046 | 2021-01-07 03:34:31 +0000 | [diff] [blame] | 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. | 
|  | 302 | func 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 | 
| Bob Badour | eef4c1c | 2022-05-16 12:20:04 -0700 | [diff] [blame] | 306 | case "*android.genNoticeModule": // contains license texts as data | 
| Bob Badour | 37af046 | 2021-01-07 03:34:31 +0000 | [diff] [blame] | 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 | 
| Bob Badour | bae8421 | 2021-09-02 17:23:48 -0700 | [diff] [blame] | 311 | case "*android.soongConfigBoolVariableDummyModule": // used for creating aliases | 
| Bob Badour | 37af046 | 2021-01-07 03:34:31 +0000 | [diff] [blame] | 312 | default: | 
|  | 313 | return false | 
|  | 314 | } | 
|  | 315 | return true | 
|  | 316 | } | 
| Paul Duffin | b0bb376 | 2021-05-06 16:48:05 +0100 | [diff] [blame] | 317 |  | 
|  | 318 | // LicenseInfo contains information about licenses for a specific module. | 
|  | 319 | type LicenseInfo struct { | 
|  | 320 | // The list of license modules this depends upon, either explicitly or through default package | 
|  | 321 | // configuration. | 
|  | 322 | Licenses []string | 
|  | 323 | } | 
|  | 324 |  | 
| Colin Cross | bc7d76c | 2023-12-12 16:39:03 -0800 | [diff] [blame] | 325 | var LicenseInfoProvider = blueprint.NewProvider[LicenseInfo]() | 
| Colin Cross | 34c7832 | 2021-10-20 16:24:13 -0700 | [diff] [blame] | 326 |  | 
|  | 327 | func init() { | 
|  | 328 | RegisterMakeVarsProvider(pctx, licensesMakeVarsProvider) | 
|  | 329 | } | 
|  | 330 |  | 
|  | 331 | func licensesMakeVarsProvider(ctx MakeVarsContext) { | 
|  | 332 | ctx.Strict("BUILD_LICENSE_METADATA", | 
|  | 333 | ctx.Config().HostToolPath(ctx, "build_license_metadata").String()) | 
| Bob Badour | 5a1fcab | 2022-05-27 19:42:16 -0700 | [diff] [blame] | 334 | ctx.Strict("COPY_LICENSE_METADATA", | 
|  | 335 | ctx.Config().HostToolPath(ctx, "copy_license_metadata").String()) | 
| Bob Badour | 6076882 | 2022-02-02 12:10:09 -0800 | [diff] [blame] | 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()) | 
| Bob Badour | 3d9a7d8 | 2022-02-28 20:12:18 -0800 | [diff] [blame] | 339 | ctx.Strict("COMPLIANCENOTICE_BOM", ctx.Config().HostToolPath(ctx, "compliancenotice_bom").String()) | 
|  | 340 | ctx.Strict("COMPLIANCENOTICE_SHIPPEDLIBS", ctx.Config().HostToolPath(ctx, "compliancenotice_shippedlibs").String()) | 
| Bob Badour | 470fd6d | 2022-04-12 20:12:59 -0700 | [diff] [blame] | 341 | ctx.Strict("COMPLIANCE_LISTSHARE", ctx.Config().HostToolPath(ctx, "compliance_listshare").String()) | 
|  | 342 | ctx.Strict("COMPLIANCE_CHECKSHARE", ctx.Config().HostToolPath(ctx, "compliance_checkshare").String()) | 
| Ibrahim Kanouche | 5797d8c | 2022-11-02 19:17:30 +0000 | [diff] [blame] | 343 | ctx.Strict("COMPLIANCE_SBOM", ctx.Config().HostToolPath(ctx, "compliance_sbom").String()) | 
| Colin Cross | 34c7832 | 2021-10-20 16:24:13 -0700 | [diff] [blame] | 344 | } |