123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261 |
- // Copyright 2021 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 (
- "sort"
- "strings"
- "github.com/google/blueprint"
- "github.com/google/blueprint/proptools"
- )
- var (
- _ = pctx.HostBinToolVariable("licenseMetadataCmd", "build_license_metadata")
- licenseMetadataRule = pctx.AndroidStaticRule("licenseMetadataRule", blueprint.RuleParams{
- Command: "${licenseMetadataCmd} -o $out @${out}.rsp",
- CommandDeps: []string{"${licenseMetadataCmd}"},
- Rspfile: "${out}.rsp",
- RspfileContent: "${args}",
- }, "args")
- )
- func buildLicenseMetadata(ctx ModuleContext, licenseMetadataFile WritablePath) {
- base := ctx.Module().base()
- if !base.Enabled() {
- return
- }
- if exemptFromRequiredApplicableLicensesProperty(ctx.Module()) {
- return
- }
- var outputFiles Paths
- if outputFileProducer, ok := ctx.Module().(OutputFileProducer); ok {
- outputFiles, _ = outputFileProducer.OutputFiles("")
- outputFiles = PathsIfNonNil(outputFiles...)
- }
- isContainer := isContainerFromFileExtensions(base.installFiles, outputFiles)
- var allDepMetadataFiles Paths
- var allDepMetadataArgs []string
- var allDepOutputFiles Paths
- var allDepMetadataDepSets []*DepSet[Path]
- ctx.VisitDirectDepsBlueprint(func(bpdep blueprint.Module) {
- dep, _ := bpdep.(Module)
- if dep == nil {
- return
- }
- if !dep.Enabled() {
- return
- }
- // Defaults add properties and dependencies that get processed on their own.
- if ctx.OtherModuleDependencyTag(dep) == DefaultsDepTag {
- return
- }
- if ctx.OtherModuleHasProvider(dep, LicenseMetadataProvider) {
- info := ctx.OtherModuleProvider(dep, LicenseMetadataProvider).(*LicenseMetadataInfo)
- allDepMetadataFiles = append(allDepMetadataFiles, info.LicenseMetadataPath)
- if isContainer || isInstallDepNeeded(dep, ctx.OtherModuleDependencyTag(dep)) {
- allDepMetadataDepSets = append(allDepMetadataDepSets, info.LicenseMetadataDepSet)
- }
- depAnnotations := licenseAnnotationsFromTag(ctx.OtherModuleDependencyTag(dep))
- allDepMetadataArgs = append(allDepMetadataArgs, info.LicenseMetadataPath.String()+depAnnotations)
- if depInstallFiles := dep.base().installFiles; len(depInstallFiles) > 0 {
- allDepOutputFiles = append(allDepOutputFiles, depInstallFiles.Paths()...)
- } else if depOutputFiles, err := outputFilesForModule(ctx, dep, ""); err == nil {
- depOutputFiles = PathsIfNonNil(depOutputFiles...)
- allDepOutputFiles = append(allDepOutputFiles, depOutputFiles...)
- }
- }
- })
- allDepMetadataFiles = SortedUniquePaths(allDepMetadataFiles)
- sort.Strings(allDepMetadataArgs)
- allDepOutputFiles = SortedUniquePaths(allDepOutputFiles)
- var orderOnlyDeps Paths
- var args []string
- if n := ctx.ModuleName(); n != "" {
- args = append(args,
- "-mn "+proptools.NinjaAndShellEscape(n))
- }
- if t := ctx.ModuleType(); t != "" {
- args = append(args,
- "-mt "+proptools.NinjaAndShellEscape(t))
- }
- args = append(args,
- "-r "+proptools.NinjaAndShellEscape(ctx.ModuleDir()),
- "-mc UNKNOWN")
- if p := base.commonProperties.Effective_package_name; p != nil {
- args = append(args,
- `-p `+proptools.NinjaAndShellEscapeIncludingSpaces(*p))
- }
- args = append(args,
- JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(base.commonProperties.Effective_license_kinds), "-k "))
- args = append(args,
- JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(base.commonProperties.Effective_license_conditions), "-c "))
- args = append(args,
- JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(base.commonProperties.Effective_license_text.Strings()), "-n "))
- if isContainer {
- transitiveDeps := Paths(NewDepSet[Path](TOPOLOGICAL, nil, allDepMetadataDepSets).ToList())
- args = append(args,
- JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(transitiveDeps.Strings()), "-d "))
- orderOnlyDeps = append(orderOnlyDeps, transitiveDeps...)
- } else {
- args = append(args,
- JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(allDepMetadataArgs), "-d "))
- orderOnlyDeps = append(orderOnlyDeps, allDepMetadataFiles...)
- }
- args = append(args,
- JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(allDepOutputFiles.Strings()), "-s "))
- // Install map
- args = append(args,
- JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(base.licenseInstallMap), "-m "))
- // Built files
- if len(outputFiles) > 0 {
- args = append(args,
- JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(outputFiles.Strings()), "-t "))
- }
- // Installed files
- args = append(args,
- JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(base.installFiles.Strings()), "-i "))
- if isContainer {
- args = append(args, "--is_container")
- }
- ctx.Build(pctx, BuildParams{
- Rule: licenseMetadataRule,
- Output: licenseMetadataFile,
- OrderOnly: orderOnlyDeps,
- Description: "license metadata",
- Args: map[string]string{
- "args": strings.Join(args, " "),
- },
- })
- ctx.SetProvider(LicenseMetadataProvider, &LicenseMetadataInfo{
- LicenseMetadataPath: licenseMetadataFile,
- LicenseMetadataDepSet: NewDepSet(TOPOLOGICAL, Paths{licenseMetadataFile}, allDepMetadataDepSets),
- })
- }
- func isContainerFromFileExtensions(installPaths InstallPaths, builtPaths Paths) bool {
- var paths Paths
- if len(installPaths) > 0 {
- paths = installPaths.Paths()
- } else {
- paths = builtPaths
- }
- for _, path := range paths {
- switch path.Ext() {
- case ".zip", ".tar", ".tgz", ".tar.gz", ".img", ".srcszip", ".apex":
- return true
- }
- }
- return false
- }
- // LicenseMetadataProvider is used to propagate license metadata paths between modules.
- var LicenseMetadataProvider = blueprint.NewProvider(&LicenseMetadataInfo{})
- // LicenseMetadataInfo stores the license metadata path for a module.
- type LicenseMetadataInfo struct {
- LicenseMetadataPath Path
- LicenseMetadataDepSet *DepSet[Path]
- }
- // licenseAnnotationsFromTag returns the LicenseAnnotations for a tag (if any) converted into
- // a string, or an empty string if there are none.
- func licenseAnnotationsFromTag(tag blueprint.DependencyTag) string {
- if annoTag, ok := tag.(LicenseAnnotationsDependencyTag); ok {
- annos := annoTag.LicenseAnnotations()
- if len(annos) > 0 {
- annoStrings := make([]string, len(annos))
- for i, s := range annos {
- annoStrings[i] = string(s)
- }
- return ":" + strings.Join(annoStrings, ",")
- }
- }
- return ""
- }
- // LicenseAnnotationsDependencyTag is implemented by dependency tags in order to provide a
- // list of license dependency annotations.
- type LicenseAnnotationsDependencyTag interface {
- LicenseAnnotations() []LicenseAnnotation
- }
- // LicenseAnnotation is an enum of annotations that can be applied to dependencies for propagating
- // license information.
- type LicenseAnnotation string
- const (
- // LicenseAnnotationSharedDependency should be returned by LicenseAnnotations implementations
- // of dependency tags when the usage of the dependency is dynamic, for example a shared library
- // linkage for native modules or as a classpath library for java modules.
- //
- // Dependency tags that need to always return LicenseAnnotationSharedDependency
- // can embed LicenseAnnotationSharedDependencyTag to implement LicenseAnnotations.
- LicenseAnnotationSharedDependency LicenseAnnotation = "dynamic"
- // LicenseAnnotationToolchain should be returned by LicenseAnnotations implementations of
- // dependency tags when the dependency is used as a toolchain.
- //
- // Dependency tags that need to always return LicenseAnnotationToolchain
- // can embed LicenseAnnotationToolchainDependencyTag to implement LicenseAnnotations.
- LicenseAnnotationToolchain LicenseAnnotation = "toolchain"
- )
- // LicenseAnnotationSharedDependencyTag can be embedded in a dependency tag to implement
- // LicenseAnnotations that always returns LicenseAnnotationSharedDependency.
- type LicenseAnnotationSharedDependencyTag struct{}
- func (LicenseAnnotationSharedDependencyTag) LicenseAnnotations() []LicenseAnnotation {
- return []LicenseAnnotation{LicenseAnnotationSharedDependency}
- }
- // LicenseAnnotationToolchainDependencyTag can be embedded in a dependency tag to implement
- // LicenseAnnotations that always returns LicenseAnnotationToolchain.
- type LicenseAnnotationToolchainDependencyTag struct{}
- func (LicenseAnnotationToolchainDependencyTag) LicenseAnnotations() []LicenseAnnotation {
- return []LicenseAnnotation{LicenseAnnotationToolchain}
- }
|