blob: c6b32432b7b952ec5277f83f81f79228bea30fbc [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 (
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
Paul Duffinb0bb3762021-05-06 16:48:05 +010035func (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
Bob Badour37af0462021-01-07 03:34:31 +000046var (
47 licensesTag = licensesDependencyTag{}
Paul Duffinb0bb3762021-05-06 16:48:05 +010048
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 Duffinf7b3d0d2021-09-02 14:29:21 +010051 _ SdkMemberDependencyTag = licensesTag
Bob Badour37af0462021-01-07 03:34:31 +000052)
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{
Paul Duffin3c298a32021-03-04 17:44:03 +000069 name: name,
Bob Badour37af0462021-01-07 03:34:31 +000070 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)
Bob Badour37af0462021-01-07 03:34:31 +0000158 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
Bob Badour37af0462021-01-07 03:34:31 +0000204 if exemptFromRequiredApplicableLicensesProperty(m) {
205 return
206 }
207
Paul Duffinb0bb3762021-05-06 16:48:05 +0100208 var licenses []string
Bob Badour37af0462021-01-07 03:34:31 +0000209 for _, module := range ctx.GetDirectDepsWithTag(licensesTag) {
210 if l, ok := module.(*licenseModule); ok {
Paul Duffinb0bb3762021-05-06 16:48:05 +0100211 licenses = append(licenses, ctx.OtherModuleName(module))
Bob Badour37af0462021-01-07 03:34:31 +0000212 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 Duffinec0836a2021-05-10 22:53:30 +0100215 mergeStringProps(&m.base().commonProperties.Effective_licenses, module.base().commonProperties.Effective_licenses...)
Bob Badour4101c712022-02-09 11:54:35 -0800216 mergeNamedPathProps(&m.base().commonProperties.Effective_license_text, module.base().commonProperties.Effective_license_text...)
Paul Duffinec0836a2021-05-10 22:53:30 +0100217 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 Badour37af0462021-01-07 03:34:31 +0000219 } 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 Duffinb0bb3762021-05-06 16:48:05 +0100228
229 // Make the license information available for other modules.
230 licenseInfo := LicenseInfo{
231 Licenses: licenses,
232 }
233 ctx.SetProvider(LicenseInfoProvider, licenseInfo)
Bob Badour37af0462021-01-07 03:34:31 +0000234}
235
236// 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 +0100237func mergeStringProps(prop *[]string, values ...string) {
238 *prop = append(*prop, values...)
239 *prop = SortedUniqueStrings(*prop)
240}
241
Bob Badour4101c712022-02-09 11:54:35 -0800242// 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) {
Paul Duffinec0836a2021-05-10 22:53:30 +0100258 *prop = append(*prop, values...)
Bob Badour4101c712022-02-09 11:54:35 -0800259 *prop = SortedUniqueNamedPaths(*prop)
Bob Badour37af0462021-01-07 03:34:31 +0000260}
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 {
Bob Badour65ee90a2021-09-02 15:33:10 -0700270 if !ctx.Config().IsEnvFalse("ANDROID_REQUIRE_LICENSES") {
Bob Badour37af0462021-01-07 03:34:31 +0000271 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
Bob Badoureef4c1c2022-05-16 12:20:04 -0700306 case "*android.genNoticeModule": // contains license texts as data
Bob Badour37af0462021-01-07 03:34:31 +0000307 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 Badourbae84212021-09-02 17:23:48 -0700311 case "*android.soongConfigBoolVariableDummyModule": // used for creating aliases
Bob Badour37af0462021-01-07 03:34:31 +0000312 default:
313 return false
314 }
315 return true
316}
Paul Duffinb0bb3762021-05-06 16:48:05 +0100317
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{})
Colin Cross34c78322021-10-20 16:24:13 -0700326
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())
Bob Badour5a1fcab2022-05-27 19:42:16 -0700334 ctx.Strict("COPY_LICENSE_METADATA",
335 ctx.Config().HostToolPath(ctx, "copy_license_metadata").String())
Bob Badour60768822022-02-02 12:10:09 -0800336 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 Badour3d9a7d82022-02-28 20:12:18 -0800339 ctx.Strict("COMPLIANCENOTICE_BOM", ctx.Config().HostToolPath(ctx, "compliancenotice_bom").String())
340 ctx.Strict("COMPLIANCENOTICE_SHIPPEDLIBS", ctx.Config().HostToolPath(ctx, "compliancenotice_shippedlibs").String())
Bob Badour470fd6d2022-04-12 20:12:59 -0700341 ctx.Strict("COMPLIANCE_LISTSHARE", ctx.Config().HostToolPath(ctx, "compliance_listshare").String())
342 ctx.Strict("COMPLIANCE_CHECKSHARE", ctx.Config().HostToolPath(ctx, "compliance_checkshare").String())
Ibrahim Kanouche5797d8c2022-11-02 19:17:30 +0000343 ctx.Strict("COMPLIANCE_SBOM", ctx.Config().HostToolPath(ctx, "compliance_sbom").String())
Colin Cross34c78322021-10-20 16:24:13 -0700344}