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