blob: 387792144d9d51429243224a8ddbc1a8e2d9b8b1 [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"
Yu Liu619b6ef2025-03-05 18:35:17 +000025 "github.com/google/blueprint/gobtools"
Bob Badour37af0462021-01-07 03:34:31 +000026)
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
Paul Duffinb0bb3762021-05-06 16:48:05 +010039func (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
Bob Badour37af0462021-01-07 03:34:31 +000050var (
51 licensesTag = licensesDependencyTag{}
Paul Duffinb0bb3762021-05-06 16:48:05 +010052
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.
Paul Duffinf7b3d0d2021-09-02 14:29:21 +010055 _ SdkMemberDependencyTag = licensesTag
Bob Badour37af0462021-01-07 03:34:31 +000056)
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
Yu Liu619b6ef2025-03-05 18:35:17 +000071type 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
Bob Badour37af0462021-01-07 03:34:31 +000096func newApplicableLicensesProperty(name string, licensesProperty *[]string) applicableLicensesProperty {
97 return applicableLicensesPropertyImpl{
Paul Duffin3c298a32021-03-04 17:44:03 +000098 name: name,
Bob Badour37af0462021-01-07 03:34:31 +000099 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) {
Colin Cross8a962802024-10-09 15:29:27 -0700138 ctx.BottomUp("licensesPackageMapper", licensesPackageMapper)
Bob Badour37af0462021-01-07 03:34:31 +0000139}
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) {
Colin Cross8a962802024-10-09 15:29:27 -0700145 ctx.BottomUp("licensesPropertyGatherer", licensesPropertyGatherer)
Bob Badour37af0462021-01-07 03:34:31 +0000146}
147
148// Registers the function that verifies the licenses and license_kinds dependency types for each module.
149func RegisterLicensesDependencyChecker(ctx RegisterMutatorsContext) {
Colin Cross8a962802024-10-09 15:29:27 -0700150 ctx.BottomUp("licensesPropertyChecker", licensesDependencyChecker)
Bob Badour37af0462021-01-07 03:34:31 +0000151}
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)
Jihoon Kang92487132024-10-29 00:12:37 +0000187
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...)
Bob Badour37af0462021-01-07 03:34:31 +0000206}
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
Bob Badour37af0462021-01-07 03:34:31 +0000251 if exemptFromRequiredApplicableLicensesProperty(m) {
252 return
253 }
254
Paul Duffinb0bb3762021-05-06 16:48:05 +0100255 var licenses []string
Yu Liu47361852025-01-23 19:28:17 +0000256 var texts NamedPaths
257 var conditions []string
258 var kinds []string
Yu Liuddccb2a2025-01-17 20:04:46 +0000259 for _, module := range ctx.GetDirectDepsProxyWithTag(licensesTag) {
260 if l, ok := OtherModuleProvider(ctx, module, LicenseInfoProvider); ok {
Paul Duffinb0bb3762021-05-06 16:48:05 +0100261 licenses = append(licenses, ctx.OtherModuleName(module))
Yu Liuddccb2a2025-01-17 20:04:46 +0000262 if m.base().commonProperties.Effective_package_name == nil && l.PackageName != nil {
263 m.base().commonProperties.Effective_package_name = l.PackageName
Bob Badour37af0462021-01-07 03:34:31 +0000264 }
Yu Liu47361852025-01-23 19:28:17 +0000265 texts = append(texts, l.EffectiveLicenseText...)
266 kinds = append(kinds, l.EffectiveLicenseKinds...)
267 conditions = append(conditions, l.EffectiveLicenseConditions...)
Bob Badour37af0462021-01-07 03:34:31 +0000268 } 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 }
Paul Duffinb0bb3762021-05-06 16:48:05 +0100277
Yu Liu47361852025-01-23 19:28:17 +0000278 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
Paul Duffinb0bb3762021-05-06 16:48:05 +0100282 // Make the license information available for other modules.
Yu Liuddccb2a2025-01-17 20:04:46 +0000283 licenseInfo := LicensesInfo{
Paul Duffinb0bb3762021-05-06 16:48:05 +0100284 Licenses: licenses,
285 }
Yu Liuddccb2a2025-01-17 20:04:46 +0000286 SetProvider(ctx, LicensesInfoProvider, licenseInfo)
Bob Badour37af0462021-01-07 03:34:31 +0000287}
288
Bob Badour4101c712022-02-09 11:54:35 -0800289// 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
Bob Badour37af0462021-01-07 03:34:31 +0000303// 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 {
Bob Badour65ee90a2021-09-02 15:33:10 -0700311 if !ctx.Config().IsEnvFalse("ANDROID_REQUIRE_LICENSES") {
Bob Badour37af0462021-01-07 03:34:31 +0000312 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
Bob Badoureef4c1c2022-05-16 12:20:04 -0700347 case "*android.genNoticeModule": // contains license texts as data
Bob Badour37af0462021-01-07 03:34:31 +0000348 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
Bob Badourbae84212021-09-02 17:23:48 -0700352 case "*android.soongConfigBoolVariableDummyModule": // used for creating aliases
Bob Badour37af0462021-01-07 03:34:31 +0000353 default:
354 return false
355 }
356 return true
357}
Paul Duffinb0bb3762021-05-06 16:48:05 +0100358
Yu Liuddccb2a2025-01-17 20:04:46 +0000359// LicensesInfo contains information about licenses for a specific module.
360type LicensesInfo struct {
Paul Duffinb0bb3762021-05-06 16:48:05 +0100361 // The list of license modules this depends upon, either explicitly or through default package
362 // configuration.
363 Licenses []string
364}
365
Yu Liuddccb2a2025-01-17 20:04:46 +0000366var LicensesInfoProvider = blueprint.NewProvider[LicensesInfo]()
Colin Cross34c78322021-10-20 16:24:13 -0700367
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())
Bob Badour5a1fcab2022-05-27 19:42:16 -0700375 ctx.Strict("COPY_LICENSE_METADATA",
376 ctx.Config().HostToolPath(ctx, "copy_license_metadata").String())
Bob Badour60768822022-02-02 12:10:09 -0800377 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())
Bob Badour3d9a7d82022-02-28 20:12:18 -0800380 ctx.Strict("COMPLIANCENOTICE_SHIPPEDLIBS", ctx.Config().HostToolPath(ctx, "compliancenotice_shippedlibs").String())
Bob Badour470fd6d2022-04-12 20:12:59 -0700381 ctx.Strict("COMPLIANCE_LISTSHARE", ctx.Config().HostToolPath(ctx, "compliance_listshare").String())
382 ctx.Strict("COMPLIANCE_CHECKSHARE", ctx.Config().HostToolPath(ctx, "compliance_checkshare").String())
Colin Cross34c78322021-10-20 16:24:13 -0700383}