df5a90502d
Previously, the processing of the license module was done in the licensesPropertyFlattener method which is called for all modules before their GenerateAndroidBuildActions method is called. This change moves the processing into the license module's GenerateAndroidBuildActions method which was previously empty to match the normal practice. Bug: 181569894 Test: m nothing Change-Id: I3736879bfa4b4d1f4e2b35770852a02d09b3db83
280 lines
9.4 KiB
Go
280 lines
9.4 KiB
Go
// Copyright 2020 Google Inc. All rights reserved.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package android
|
|
|
|
import (
|
|
"reflect"
|
|
"sync"
|
|
|
|
"github.com/google/blueprint"
|
|
)
|
|
|
|
// Adds cross-cutting licenses dependency to propagate license metadata through the build system.
|
|
//
|
|
// Stage 1 - bottom-up records package-level default_applicable_licenses property mapped by package name.
|
|
// Stage 2 - bottom-up converts licenses property or package default_applicable_licenses to dependencies.
|
|
// Stage 3 - bottom-up type-checks every added applicable license dependency and license_kind dependency.
|
|
// Stage 4 - GenerateBuildActions calculates properties for the union of license kinds, conditions and texts.
|
|
|
|
type licensesDependencyTag struct {
|
|
blueprint.BaseDependencyTag
|
|
}
|
|
|
|
var (
|
|
licensesTag = licensesDependencyTag{}
|
|
)
|
|
|
|
// Describes the property provided by a module to reference applicable licenses.
|
|
type applicableLicensesProperty interface {
|
|
// The name of the property. e.g. default_applicable_licenses or licenses
|
|
getName() string
|
|
// The values assigned to the property. (Must reference license modules.)
|
|
getStrings() []string
|
|
}
|
|
|
|
type applicableLicensesPropertyImpl struct {
|
|
name string
|
|
licensesProperty *[]string
|
|
}
|
|
|
|
func newApplicableLicensesProperty(name string, licensesProperty *[]string) applicableLicensesProperty {
|
|
return applicableLicensesPropertyImpl{
|
|
name: name,
|
|
licensesProperty: licensesProperty,
|
|
}
|
|
}
|
|
|
|
func (p applicableLicensesPropertyImpl) getName() string {
|
|
return p.name
|
|
}
|
|
|
|
func (p applicableLicensesPropertyImpl) getStrings() []string {
|
|
return *p.licensesProperty
|
|
}
|
|
|
|
// Set the primary applicable licenses property for a module.
|
|
func setPrimaryLicensesProperty(module Module, name string, licensesProperty *[]string) {
|
|
module.base().primaryLicensesProperty = newApplicableLicensesProperty(name, licensesProperty)
|
|
}
|
|
|
|
// Storage blob for a package's default_applicable_licenses mapped by package directory.
|
|
type licensesContainer struct {
|
|
licenses []string
|
|
}
|
|
|
|
func (r licensesContainer) getLicenses() []string {
|
|
return r.licenses
|
|
}
|
|
|
|
var packageDefaultLicensesMap = NewOnceKey("packageDefaultLicensesMap")
|
|
|
|
// The map from package dir name to default applicable licenses as a licensesContainer.
|
|
func moduleToPackageDefaultLicensesMap(config Config) *sync.Map {
|
|
return config.Once(packageDefaultLicensesMap, func() interface{} {
|
|
return &sync.Map{}
|
|
}).(*sync.Map)
|
|
}
|
|
|
|
// Registers the function that maps each package to its default_applicable_licenses.
|
|
//
|
|
// This goes before defaults expansion so the defaults can pick up the package default.
|
|
func RegisterLicensesPackageMapper(ctx RegisterMutatorsContext) {
|
|
ctx.BottomUp("licensesPackageMapper", licensesPackageMapper).Parallel()
|
|
}
|
|
|
|
// Registers the function that gathers the license dependencies for each module.
|
|
//
|
|
// This goes after defaults expansion so that it can pick up default licenses and before visibility enforcement.
|
|
func RegisterLicensesPropertyGatherer(ctx RegisterMutatorsContext) {
|
|
ctx.BottomUp("licensesPropertyGatherer", licensesPropertyGatherer).Parallel()
|
|
}
|
|
|
|
// Registers the function that verifies the licenses and license_kinds dependency types for each module.
|
|
func RegisterLicensesDependencyChecker(ctx RegisterMutatorsContext) {
|
|
ctx.BottomUp("licensesPropertyChecker", licensesDependencyChecker).Parallel()
|
|
}
|
|
|
|
// Maps each package to its default applicable licenses.
|
|
func licensesPackageMapper(ctx BottomUpMutatorContext) {
|
|
p, ok := ctx.Module().(*packageModule)
|
|
if !ok {
|
|
return
|
|
}
|
|
|
|
licenses := getLicenses(ctx, p)
|
|
|
|
dir := ctx.ModuleDir()
|
|
c := makeLicensesContainer(licenses)
|
|
moduleToPackageDefaultLicensesMap(ctx.Config()).Store(dir, c)
|
|
}
|
|
|
|
// Copies the default_applicable_licenses property values for mapping by package directory.
|
|
func makeLicensesContainer(propVals []string) licensesContainer {
|
|
licenses := make([]string, 0, len(propVals))
|
|
licenses = append(licenses, propVals...)
|
|
|
|
return licensesContainer{licenses}
|
|
}
|
|
|
|
// Gathers the applicable licenses into dependency references after defaults expansion.
|
|
func licensesPropertyGatherer(ctx BottomUpMutatorContext) {
|
|
m, ok := ctx.Module().(Module)
|
|
if !ok {
|
|
return
|
|
}
|
|
|
|
if exemptFromRequiredApplicableLicensesProperty(m) {
|
|
return
|
|
}
|
|
|
|
licenses := getLicenses(ctx, m)
|
|
|
|
ctx.AddVariationDependencies(nil, licensesTag, licenses...)
|
|
}
|
|
|
|
// Verifies the license and license_kind dependencies are each the correct kind of module.
|
|
func licensesDependencyChecker(ctx BottomUpMutatorContext) {
|
|
m, ok := ctx.Module().(Module)
|
|
if !ok {
|
|
return
|
|
}
|
|
|
|
// license modules have no licenses, but license_kinds must refer to license_kind modules
|
|
if _, ok := m.(*licenseModule); ok {
|
|
for _, module := range ctx.GetDirectDepsWithTag(licenseKindTag) {
|
|
if _, ok := module.(*licenseKindModule); !ok {
|
|
ctx.ModuleErrorf("license_kinds property %q is not a license_kind module", ctx.OtherModuleName(module))
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
if exemptFromRequiredApplicableLicensesProperty(m) {
|
|
return
|
|
}
|
|
|
|
for _, module := range ctx.GetDirectDepsWithTag(licensesTag) {
|
|
if _, ok := module.(*licenseModule); !ok {
|
|
propertyName := "licenses"
|
|
primaryProperty := m.base().primaryLicensesProperty
|
|
if primaryProperty != nil {
|
|
propertyName = primaryProperty.getName()
|
|
}
|
|
ctx.ModuleErrorf("%s property %q is not a license module", propertyName, ctx.OtherModuleName(module))
|
|
}
|
|
}
|
|
}
|
|
|
|
// Flattens license and license_kind dependencies into calculated properties.
|
|
//
|
|
// Re-validates applicable licenses properties refer only to license modules and license_kinds properties refer
|
|
// only to license_kind modules.
|
|
func licensesPropertyFlattener(ctx ModuleContext) {
|
|
m, ok := ctx.Module().(Module)
|
|
if !ok {
|
|
return
|
|
}
|
|
|
|
if exemptFromRequiredApplicableLicensesProperty(m) {
|
|
return
|
|
}
|
|
|
|
for _, module := range ctx.GetDirectDepsWithTag(licensesTag) {
|
|
if l, ok := module.(*licenseModule); ok {
|
|
if m.base().commonProperties.Effective_package_name == nil && l.properties.Package_name != nil {
|
|
m.base().commonProperties.Effective_package_name = l.properties.Package_name
|
|
}
|
|
mergeProps(&m.base().commonProperties.Effective_licenses, module.base().commonProperties.Effective_licenses...)
|
|
mergeProps(&m.base().commonProperties.Effective_license_text, module.base().commonProperties.Effective_license_text...)
|
|
mergeProps(&m.base().commonProperties.Effective_license_kinds, module.base().commonProperties.Effective_license_kinds...)
|
|
mergeProps(&m.base().commonProperties.Effective_license_conditions, module.base().commonProperties.Effective_license_conditions...)
|
|
} else {
|
|
propertyName := "licenses"
|
|
primaryProperty := m.base().primaryLicensesProperty
|
|
if primaryProperty != nil {
|
|
propertyName = primaryProperty.getName()
|
|
}
|
|
ctx.ModuleErrorf("%s property %q is not a license module", propertyName, ctx.OtherModuleName(module))
|
|
}
|
|
}
|
|
}
|
|
|
|
// Update a property string array with a distinct union of its values and a list of new values.
|
|
func mergeProps(prop *[]string, values ...string) {
|
|
s := make(map[string]bool)
|
|
for _, v := range *prop {
|
|
s[v] = true
|
|
}
|
|
for _, v := range values {
|
|
s[v] = true
|
|
}
|
|
*prop = []string{}
|
|
*prop = append(*prop, SortedStringKeys(s)...)
|
|
}
|
|
|
|
// Get the licenses property falling back to the package default.
|
|
func getLicenses(ctx BaseModuleContext, module Module) []string {
|
|
if exemptFromRequiredApplicableLicensesProperty(module) {
|
|
return nil
|
|
}
|
|
|
|
primaryProperty := module.base().primaryLicensesProperty
|
|
if primaryProperty == nil {
|
|
if ctx.Config().IsEnvTrue("ANDROID_REQUIRE_LICENSES") {
|
|
ctx.ModuleErrorf("module type %q must have an applicable licenses property", ctx.OtherModuleType(module))
|
|
}
|
|
return nil
|
|
}
|
|
|
|
licenses := primaryProperty.getStrings()
|
|
if len(licenses) > 0 {
|
|
s := make(map[string]bool)
|
|
for _, l := range licenses {
|
|
if _, ok := s[l]; ok {
|
|
ctx.ModuleErrorf("duplicate %q %s", l, primaryProperty.getName())
|
|
}
|
|
s[l] = true
|
|
}
|
|
return licenses
|
|
}
|
|
|
|
dir := ctx.OtherModuleDir(module)
|
|
|
|
moduleToApplicableLicenses := moduleToPackageDefaultLicensesMap(ctx.Config())
|
|
value, ok := moduleToApplicableLicenses.Load(dir)
|
|
var c licensesContainer
|
|
if ok {
|
|
c = value.(licensesContainer)
|
|
} else {
|
|
c = licensesContainer{}
|
|
}
|
|
return c.getLicenses()
|
|
}
|
|
|
|
// Returns whether a module is an allowed list of modules that do not have or need applicable licenses.
|
|
func exemptFromRequiredApplicableLicensesProperty(module Module) bool {
|
|
switch reflect.TypeOf(module).String() {
|
|
case "*android.licenseModule": // is a license, doesn't need one
|
|
case "*android.licenseKindModule": // is a license, doesn't need one
|
|
case "*android.NamespaceModule": // just partitions things, doesn't add anything
|
|
case "*android.soongConfigModuleTypeModule": // creates aliases for modules with licenses
|
|
case "*android.soongConfigModuleTypeImport": // creates aliases for modules with licenses
|
|
case "*android.soongConfigStringVariableDummyModule": // used for creating aliases
|
|
case "*android.SoongConfigBoolVariableDummyModule": // used for creating aliases
|
|
default:
|
|
return false
|
|
}
|
|
return true
|
|
}
|