123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344 |
- // 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
- }
- func (l licensesDependencyTag) SdkMemberType(Module) SdkMemberType {
- // Add the supplied module to the sdk as a license module.
- return LicenseModuleSdkMemberType
- }
- func (l licensesDependencyTag) ExportMember() bool {
- // The license module will only every be referenced from within the sdk. This will ensure that it
- // gets a unique name and so avoid clashing with the original license module.
- return false
- }
- var (
- licensesTag = licensesDependencyTag{}
- // License modules, i.e. modules depended upon via a licensesTag, must be automatically added to
- // any sdk/module_exports to which their referencing module is a member.
- _ SdkMemberDependencyTag = licensesTag
- )
- // 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
- }
- var licenses []string
- for _, module := range ctx.GetDirectDepsWithTag(licensesTag) {
- if l, ok := module.(*licenseModule); ok {
- licenses = append(licenses, ctx.OtherModuleName(module))
- if m.base().commonProperties.Effective_package_name == nil && l.properties.Package_name != nil {
- m.base().commonProperties.Effective_package_name = l.properties.Package_name
- }
- mergeStringProps(&m.base().commonProperties.Effective_licenses, module.base().commonProperties.Effective_licenses...)
- mergeNamedPathProps(&m.base().commonProperties.Effective_license_text, module.base().commonProperties.Effective_license_text...)
- mergeStringProps(&m.base().commonProperties.Effective_license_kinds, module.base().commonProperties.Effective_license_kinds...)
- mergeStringProps(&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))
- }
- }
- // Make the license information available for other modules.
- licenseInfo := LicenseInfo{
- Licenses: licenses,
- }
- ctx.SetProvider(LicenseInfoProvider, licenseInfo)
- }
- // Update a property string array with a distinct union of its values and a list of new values.
- func mergeStringProps(prop *[]string, values ...string) {
- *prop = append(*prop, values...)
- *prop = SortedUniqueStrings(*prop)
- }
- // Update a property NamedPath array with a distinct union of its values and a list of new values.
- func namePathProps(prop *NamedPaths, name *string, values ...Path) {
- if name == nil {
- for _, value := range values {
- *prop = append(*prop, NamedPath{value, ""})
- }
- } else {
- for _, value := range values {
- *prop = append(*prop, NamedPath{value, *name})
- }
- }
- *prop = SortedUniqueNamedPaths(*prop)
- }
- // Update a property NamedPath array with a distinct union of its values and a list of new values.
- func mergeNamedPathProps(prop *NamedPaths, values ...NamedPath) {
- *prop = append(*prop, values...)
- *prop = SortedUniqueNamedPaths(*prop)
- }
- // 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().IsEnvFalse("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.genNoticeModule": // contains license texts as data
- 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
- }
- // LicenseInfo contains information about licenses for a specific module.
- type LicenseInfo struct {
- // The list of license modules this depends upon, either explicitly or through default package
- // configuration.
- Licenses []string
- }
- var LicenseInfoProvider = blueprint.NewProvider(LicenseInfo{})
- func init() {
- RegisterMakeVarsProvider(pctx, licensesMakeVarsProvider)
- }
- func licensesMakeVarsProvider(ctx MakeVarsContext) {
- ctx.Strict("BUILD_LICENSE_METADATA",
- ctx.Config().HostToolPath(ctx, "build_license_metadata").String())
- ctx.Strict("COPY_LICENSE_METADATA",
- ctx.Config().HostToolPath(ctx, "copy_license_metadata").String())
- ctx.Strict("HTMLNOTICE", ctx.Config().HostToolPath(ctx, "htmlnotice").String())
- ctx.Strict("XMLNOTICE", ctx.Config().HostToolPath(ctx, "xmlnotice").String())
- ctx.Strict("TEXTNOTICE", ctx.Config().HostToolPath(ctx, "textnotice").String())
- ctx.Strict("COMPLIANCENOTICE_BOM", ctx.Config().HostToolPath(ctx, "compliancenotice_bom").String())
- ctx.Strict("COMPLIANCENOTICE_SHIPPEDLIBS", ctx.Config().HostToolPath(ctx, "compliancenotice_shippedlibs").String())
- ctx.Strict("COMPLIANCE_LISTSHARE", ctx.Config().HostToolPath(ctx, "compliance_listshare").String())
- ctx.Strict("COMPLIANCE_CHECKSHARE", ctx.Config().HostToolPath(ctx, "compliance_checkshare").String())
- ctx.Strict("COMPLIANCE_SBOM", ctx.Config().HostToolPath(ctx, "compliance_sbom").String())
- }
|