blob: 48c1383f6d9922c3fe6a1a47ef656be5f13d9e7b [file] [log] [blame]
Colin Cross4acaea92021-12-10 23:05:02 +00001// Copyright 2021 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 "fmt"
19 "sort"
20 "strings"
21
22 "github.com/google/blueprint"
23 "github.com/google/blueprint/proptools"
24)
25
26var (
27 _ = pctx.HostBinToolVariable("licenseMetadataCmd", "build_license_metadata")
28
29 licenseMetadataRule = pctx.AndroidStaticRule("licenseMetadataRule", blueprint.RuleParams{
30 Command: "${licenseMetadataCmd} -o $out @${out}.rsp",
31 CommandDeps: []string{"${licenseMetadataCmd}"},
32 Rspfile: "${out}.rsp",
33 RspfileContent: "${args}",
34 }, "args")
35)
36
Colin Crossaa1cab02022-01-28 14:49:24 -080037func buildLicenseMetadata(ctx ModuleContext, licenseMetadataFile WritablePath) {
Colin Cross4acaea92021-12-10 23:05:02 +000038 base := ctx.Module().base()
39
40 if !base.Enabled() {
41 return
42 }
43
44 if exemptFromRequiredApplicableLicensesProperty(ctx.Module()) {
45 return
46 }
47
Colin Crossaff21fb2022-01-12 10:57:57 -080048 var outputFiles Paths
49 if outputFileProducer, ok := ctx.Module().(OutputFileProducer); ok {
50 outputFiles, _ = outputFileProducer.OutputFiles("")
51 outputFiles = PathsIfNonNil(outputFiles...)
52 }
53
54 isContainer := isContainerFromFileExtensions(base.installFiles, outputFiles)
55
Colin Cross4acaea92021-12-10 23:05:02 +000056 var allDepMetadataFiles Paths
57 var allDepMetadataArgs []string
58 var allDepOutputFiles Paths
Colin Crossaff21fb2022-01-12 10:57:57 -080059 var allDepMetadataDepSets []*PathsDepSet
Colin Cross4acaea92021-12-10 23:05:02 +000060
61 ctx.VisitDirectDepsBlueprint(func(bpdep blueprint.Module) {
62 dep, _ := bpdep.(Module)
63 if dep == nil {
64 return
65 }
66 if !dep.Enabled() {
67 return
68 }
69
70 if ctx.OtherModuleHasProvider(dep, LicenseMetadataProvider) {
71 info := ctx.OtherModuleProvider(dep, LicenseMetadataProvider).(*LicenseMetadataInfo)
72 allDepMetadataFiles = append(allDepMetadataFiles, info.LicenseMetadataPath)
Colin Crossaff21fb2022-01-12 10:57:57 -080073 if isContainer || IsInstallDepNeeded(ctx.OtherModuleDependencyTag(dep)) {
74 allDepMetadataDepSets = append(allDepMetadataDepSets, info.LicenseMetadataDepSet)
75 }
Colin Cross4acaea92021-12-10 23:05:02 +000076
77 depAnnotations := licenseAnnotationsFromTag(ctx.OtherModuleDependencyTag(dep))
78
79 allDepMetadataArgs = append(allDepMetadataArgs, info.LicenseMetadataPath.String()+depAnnotations)
80
81 if depInstallFiles := dep.base().installFiles; len(depInstallFiles) > 0 {
82 allDepOutputFiles = append(allDepOutputFiles, depInstallFiles.Paths()...)
83 } else if depOutputFiles, err := outputFilesForModule(ctx, dep, ""); err == nil {
84 depOutputFiles = PathsIfNonNil(depOutputFiles...)
85 allDepOutputFiles = append(allDepOutputFiles, depOutputFiles...)
86 }
87 }
88 })
89
90 allDepMetadataFiles = SortedUniquePaths(allDepMetadataFiles)
91 sort.Strings(allDepMetadataArgs)
92 allDepOutputFiles = SortedUniquePaths(allDepOutputFiles)
93
94 var orderOnlyDeps Paths
95 var args []string
96
97 if t := ctx.ModuleType(); t != "" {
98 args = append(args,
99 "-mt "+proptools.NinjaAndShellEscape(t))
100 }
101
102 args = append(args,
103 "-r "+proptools.NinjaAndShellEscape(ctx.ModuleDir()),
104 "-mc UNKNOWN")
105
106 if p := base.commonProperties.Effective_package_name; p != nil {
107 args = append(args,
Bob Badoure8febee2022-06-08 17:59:01 -0700108 `-p "`+proptools.NinjaAndShellEscape(*p)+`"`)
Colin Cross4acaea92021-12-10 23:05:02 +0000109 }
110
111 args = append(args,
112 JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(base.commonProperties.Effective_license_kinds), "-k "))
113
114 args = append(args,
115 JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(base.commonProperties.Effective_license_conditions), "-c "))
116
117 args = append(args,
118 JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(base.commonProperties.Effective_license_text.Strings()), "-n "))
119
Colin Crossaff21fb2022-01-12 10:57:57 -0800120 if isContainer {
Colin Crossaa1cab02022-01-28 14:49:24 -0800121 transitiveDeps := newPathsDepSet(nil, allDepMetadataDepSets).ToList()
Colin Crossaff21fb2022-01-12 10:57:57 -0800122 args = append(args,
Colin Crossaa1cab02022-01-28 14:49:24 -0800123 JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(transitiveDeps.Strings()), "-d "))
124 orderOnlyDeps = append(orderOnlyDeps, transitiveDeps...)
Colin Crossaff21fb2022-01-12 10:57:57 -0800125 } else {
126 args = append(args,
127 JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(allDepMetadataArgs), "-d "))
128 orderOnlyDeps = append(orderOnlyDeps, allDepMetadataFiles...)
129 }
Colin Cross4acaea92021-12-10 23:05:02 +0000130
131 args = append(args,
132 JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(allDepOutputFiles.Strings()), "-s "))
133
134 // Install map
135 args = append(args,
136 JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(base.licenseInstallMap), "-m "))
137
138 // Built files
Colin Cross4acaea92021-12-10 23:05:02 +0000139 if len(outputFiles) > 0 {
140 args = append(args,
141 JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(outputFiles.Strings()), "-t "))
142 } else {
143 args = append(args, fmt.Sprintf("-t //%s:%s", ctx.ModuleDir(), ctx.ModuleName()))
144 }
145
146 // Installed files
147 args = append(args,
148 JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(base.installFiles.Strings()), "-i "))
149
Colin Cross4acaea92021-12-10 23:05:02 +0000150 if isContainer {
151 args = append(args, "--is_container")
152 }
153
Colin Cross4acaea92021-12-10 23:05:02 +0000154 ctx.Build(pctx, BuildParams{
155 Rule: licenseMetadataRule,
156 Output: licenseMetadataFile,
157 OrderOnly: orderOnlyDeps,
158 Description: "license metadata",
159 Args: map[string]string{
160 "args": strings.Join(args, " "),
161 },
162 })
163
164 ctx.SetProvider(LicenseMetadataProvider, &LicenseMetadataInfo{
Colin Crossaff21fb2022-01-12 10:57:57 -0800165 LicenseMetadataPath: licenseMetadataFile,
166 LicenseMetadataDepSet: newPathsDepSet(Paths{licenseMetadataFile}, allDepMetadataDepSets),
Colin Cross4acaea92021-12-10 23:05:02 +0000167 })
168}
169
170func isContainerFromFileExtensions(installPaths InstallPaths, builtPaths Paths) bool {
171 var paths Paths
172 if len(installPaths) > 0 {
173 paths = installPaths.Paths()
174 } else {
175 paths = builtPaths
176 }
177
178 for _, path := range paths {
179 switch path.Ext() {
180 case ".zip", ".tar", ".tgz", ".tar.gz", ".img", ".srcszip", ".apex":
181 return true
182 }
183 }
184
185 return false
186}
187
188// LicenseMetadataProvider is used to propagate license metadata paths between modules.
189var LicenseMetadataProvider = blueprint.NewProvider(&LicenseMetadataInfo{})
190
191// LicenseMetadataInfo stores the license metadata path for a module.
192type LicenseMetadataInfo struct {
Colin Crossaff21fb2022-01-12 10:57:57 -0800193 LicenseMetadataPath Path
194 LicenseMetadataDepSet *PathsDepSet
Colin Cross4acaea92021-12-10 23:05:02 +0000195}
196
197// licenseAnnotationsFromTag returns the LicenseAnnotations for a tag (if any) converted into
198// a string, or an empty string if there are none.
199func licenseAnnotationsFromTag(tag blueprint.DependencyTag) string {
200 if annoTag, ok := tag.(LicenseAnnotationsDependencyTag); ok {
201 annos := annoTag.LicenseAnnotations()
202 if len(annos) > 0 {
203 annoStrings := make([]string, len(annos))
204 for i, s := range annos {
205 annoStrings[i] = string(s)
206 }
207 return ":" + strings.Join(annoStrings, ",")
208 }
209 }
210 return ""
211}
212
213// LicenseAnnotationsDependencyTag is implemented by dependency tags in order to provide a
214// list of license dependency annotations.
215type LicenseAnnotationsDependencyTag interface {
216 LicenseAnnotations() []LicenseAnnotation
217}
218
219// LicenseAnnotation is an enum of annotations that can be applied to dependencies for propagating
220// license information.
221type LicenseAnnotation string
222
223const (
224 // LicenseAnnotationSharedDependency should be returned by LicenseAnnotations implementations
225 // of dependency tags when the usage of the dependency is dynamic, for example a shared library
226 // linkage for native modules or as a classpath library for java modules.
Colin Crossce564252022-01-12 11:13:32 -0800227 //
228 // Dependency tags that need to always return LicenseAnnotationSharedDependency
229 // can embed LicenseAnnotationSharedDependencyTag to implement LicenseAnnotations.
Colin Cross4acaea92021-12-10 23:05:02 +0000230 LicenseAnnotationSharedDependency LicenseAnnotation = "dynamic"
231
232 // LicenseAnnotationToolchain should be returned by LicenseAnnotations implementations of
233 // dependency tags when the dependency is used as a toolchain.
234 //
235 // Dependency tags that need to always return LicenseAnnotationToolchain
236 // can embed LicenseAnnotationToolchainDependencyTag to implement LicenseAnnotations.
237 LicenseAnnotationToolchain LicenseAnnotation = "toolchain"
238)
239
Colin Crossce564252022-01-12 11:13:32 -0800240// LicenseAnnotationSharedDependencyTag can be embedded in a dependency tag to implement
241// LicenseAnnotations that always returns LicenseAnnotationSharedDependency.
242type LicenseAnnotationSharedDependencyTag struct{}
243
244func (LicenseAnnotationSharedDependencyTag) LicenseAnnotations() []LicenseAnnotation {
245 return []LicenseAnnotation{LicenseAnnotationSharedDependency}
246}
247
Colin Cross4acaea92021-12-10 23:05:02 +0000248// LicenseAnnotationToolchainDependencyTag can be embedded in a dependency tag to implement
249// LicenseAnnotations that always returns LicenseAnnotationToolchain.
250type LicenseAnnotationToolchainDependencyTag struct{}
251
252func (LicenseAnnotationToolchainDependencyTag) LicenseAnnotations() []LicenseAnnotation {
253 return []LicenseAnnotation{LicenseAnnotationToolchain}
254}