blob: f92563862989ee3b416c243433cc131d0ce790cf [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 (
Colin Cross4acaea92021-12-10 23:05:02 +000018 "sort"
19 "strings"
20
21 "github.com/google/blueprint"
22 "github.com/google/blueprint/proptools"
23)
24
25var (
26 _ = pctx.HostBinToolVariable("licenseMetadataCmd", "build_license_metadata")
27
28 licenseMetadataRule = pctx.AndroidStaticRule("licenseMetadataRule", blueprint.RuleParams{
29 Command: "${licenseMetadataCmd} -o $out @${out}.rsp",
30 CommandDeps: []string{"${licenseMetadataCmd}"},
31 Rspfile: "${out}.rsp",
32 RspfileContent: "${args}",
33 }, "args")
34)
35
Yu Liuddc28332024-08-09 22:48:30 +000036func buildLicenseMetadata(ctx *moduleContext, licenseMetadataFile WritablePath) {
Colin Cross4acaea92021-12-10 23:05:02 +000037 base := ctx.Module().base()
38
Cole Fausta963b942024-04-11 17:43:00 -070039 if !base.Enabled(ctx) {
Colin Cross4acaea92021-12-10 23:05:02 +000040 return
41 }
42
43 if exemptFromRequiredApplicableLicensesProperty(ctx.Module()) {
44 return
45 }
46
Colin Crossaff21fb2022-01-12 10:57:57 -080047 var outputFiles Paths
mrziwang01201ed2024-07-11 10:21:57 -070048 if outputFiles, err := outputFilesForModule(ctx, ctx.Module(), ""); err == nil {
Colin Crossaff21fb2022-01-12 10:57:57 -080049 outputFiles = PathsIfNonNil(outputFiles...)
50 }
51
Colin Cross5c1d5fb2023-11-15 12:39:40 -080052 // Only pass the last installed file to isContainerFromFileExtensions so a *.zip file in test data
53 // doesn't mark the whole module as a container.
54 var installFiles InstallPaths
Yu Liuddc28332024-08-09 22:48:30 +000055 if len(ctx.installFiles) > 0 {
56 installFiles = InstallPaths{ctx.installFiles[len(ctx.installFiles)-1]}
Colin Cross5c1d5fb2023-11-15 12:39:40 -080057 }
58
59 isContainer := isContainerFromFileExtensions(installFiles, outputFiles)
Colin Crossaff21fb2022-01-12 10:57:57 -080060
Colin Cross4acaea92021-12-10 23:05:02 +000061 var allDepMetadataFiles Paths
62 var allDepMetadataArgs []string
63 var allDepOutputFiles Paths
Colin Crossc85750b2022-04-21 12:50:51 -070064 var allDepMetadataDepSets []*DepSet[Path]
Colin Cross4acaea92021-12-10 23:05:02 +000065
Colin Cross648daea2024-09-12 14:35:29 -070066 ctx.VisitDirectDeps(func(dep Module) {
Cole Fausta963b942024-04-11 17:43:00 -070067 if !dep.Enabled(ctx) {
Colin Cross4acaea92021-12-10 23:05:02 +000068 return
69 }
70
Bob Badour7fd521e2022-07-29 11:18:12 -070071 // Defaults add properties and dependencies that get processed on their own.
72 if ctx.OtherModuleDependencyTag(dep) == DefaultsDepTag {
73 return
74 }
Jiyong Park8bcf3c62024-03-18 18:37:10 +090075 // The required dependencies just say modules A and B should be installed together.
76 // It doesn't mean that one is built using the other.
77 if ctx.OtherModuleDependencyTag(dep) == RequiredDepTag {
78 return
79 }
Bob Badour7fd521e2022-07-29 11:18:12 -070080
Colin Cross313aa542023-12-13 13:47:44 -080081 if info, ok := OtherModuleProvider(ctx, dep, LicenseMetadataProvider); ok {
Colin Cross4acaea92021-12-10 23:05:02 +000082 allDepMetadataFiles = append(allDepMetadataFiles, info.LicenseMetadataPath)
Colin Crossbd3a16b2023-04-25 11:30:51 -070083 if isContainer || isInstallDepNeeded(dep, ctx.OtherModuleDependencyTag(dep)) {
Colin Crossaff21fb2022-01-12 10:57:57 -080084 allDepMetadataDepSets = append(allDepMetadataDepSets, info.LicenseMetadataDepSet)
85 }
Colin Cross4acaea92021-12-10 23:05:02 +000086
87 depAnnotations := licenseAnnotationsFromTag(ctx.OtherModuleDependencyTag(dep))
88
89 allDepMetadataArgs = append(allDepMetadataArgs, info.LicenseMetadataPath.String()+depAnnotations)
90
Yu Liud46e5ae2024-08-15 18:46:17 +000091 if depInstallFiles := OtherModuleProviderOrDefault(ctx, dep, InstallFilesProvider).InstallFiles; len(depInstallFiles) > 0 {
Colin Cross4acaea92021-12-10 23:05:02 +000092 allDepOutputFiles = append(allDepOutputFiles, depInstallFiles.Paths()...)
93 } else if depOutputFiles, err := outputFilesForModule(ctx, dep, ""); err == nil {
94 depOutputFiles = PathsIfNonNil(depOutputFiles...)
95 allDepOutputFiles = append(allDepOutputFiles, depOutputFiles...)
96 }
97 }
98 })
99
100 allDepMetadataFiles = SortedUniquePaths(allDepMetadataFiles)
101 sort.Strings(allDepMetadataArgs)
102 allDepOutputFiles = SortedUniquePaths(allDepOutputFiles)
103
104 var orderOnlyDeps Paths
105 var args []string
106
Ibrahim Kanouche49920782022-10-13 18:37:24 +0000107 if n := ctx.ModuleName(); n != "" {
108 args = append(args,
109 "-mn "+proptools.NinjaAndShellEscape(n))
110 }
111
Colin Cross4acaea92021-12-10 23:05:02 +0000112 if t := ctx.ModuleType(); t != "" {
113 args = append(args,
114 "-mt "+proptools.NinjaAndShellEscape(t))
115 }
116
117 args = append(args,
118 "-r "+proptools.NinjaAndShellEscape(ctx.ModuleDir()),
119 "-mc UNKNOWN")
120
121 if p := base.commonProperties.Effective_package_name; p != nil {
122 args = append(args,
Bob Badoura10d5a22022-06-21 11:12:01 -0700123 `-p `+proptools.NinjaAndShellEscapeIncludingSpaces(*p))
Colin Cross4acaea92021-12-10 23:05:02 +0000124 }
125
126 args = append(args,
127 JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(base.commonProperties.Effective_license_kinds), "-k "))
128
129 args = append(args,
130 JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(base.commonProperties.Effective_license_conditions), "-c "))
131
132 args = append(args,
133 JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(base.commonProperties.Effective_license_text.Strings()), "-n "))
134
Colin Crossaff21fb2022-01-12 10:57:57 -0800135 if isContainer {
Colin Crossc85750b2022-04-21 12:50:51 -0700136 transitiveDeps := Paths(NewDepSet[Path](TOPOLOGICAL, nil, allDepMetadataDepSets).ToList())
Colin Crossaff21fb2022-01-12 10:57:57 -0800137 args = append(args,
Colin Crossaa1cab02022-01-28 14:49:24 -0800138 JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(transitiveDeps.Strings()), "-d "))
139 orderOnlyDeps = append(orderOnlyDeps, transitiveDeps...)
Colin Crossaff21fb2022-01-12 10:57:57 -0800140 } else {
141 args = append(args,
142 JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(allDepMetadataArgs), "-d "))
143 orderOnlyDeps = append(orderOnlyDeps, allDepMetadataFiles...)
144 }
Colin Cross4acaea92021-12-10 23:05:02 +0000145
146 args = append(args,
147 JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(allDepOutputFiles.Strings()), "-s "))
148
149 // Install map
150 args = append(args,
Yu Liubad1eef2024-08-21 22:37:35 +0000151 JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(ctx.licenseInstallMap), "-m "))
Colin Cross4acaea92021-12-10 23:05:02 +0000152
153 // Built files
Colin Cross4acaea92021-12-10 23:05:02 +0000154 if len(outputFiles) > 0 {
155 args = append(args,
156 JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(outputFiles.Strings()), "-t "))
Colin Cross4acaea92021-12-10 23:05:02 +0000157 }
158
159 // Installed files
160 args = append(args,
Yu Liuddc28332024-08-09 22:48:30 +0000161 JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(ctx.installFiles.Strings()), "-i "))
Colin Cross4acaea92021-12-10 23:05:02 +0000162
Colin Cross4acaea92021-12-10 23:05:02 +0000163 if isContainer {
164 args = append(args, "--is_container")
165 }
166
Colin Cross4acaea92021-12-10 23:05:02 +0000167 ctx.Build(pctx, BuildParams{
168 Rule: licenseMetadataRule,
169 Output: licenseMetadataFile,
170 OrderOnly: orderOnlyDeps,
171 Description: "license metadata",
172 Args: map[string]string{
173 "args": strings.Join(args, " "),
174 },
175 })
176
Colin Cross40213022023-12-13 15:19:49 -0800177 SetProvider(ctx, LicenseMetadataProvider, &LicenseMetadataInfo{
Colin Crossaff21fb2022-01-12 10:57:57 -0800178 LicenseMetadataPath: licenseMetadataFile,
Colin Crossc85750b2022-04-21 12:50:51 -0700179 LicenseMetadataDepSet: NewDepSet(TOPOLOGICAL, Paths{licenseMetadataFile}, allDepMetadataDepSets),
Colin Cross4acaea92021-12-10 23:05:02 +0000180 })
181}
182
183func isContainerFromFileExtensions(installPaths InstallPaths, builtPaths Paths) bool {
184 var paths Paths
185 if len(installPaths) > 0 {
186 paths = installPaths.Paths()
187 } else {
188 paths = builtPaths
189 }
190
191 for _, path := range paths {
192 switch path.Ext() {
Jooyung Han4191da72024-05-03 11:41:11 +0900193 case ".zip", ".tar", ".tgz", ".tar.gz", ".img", ".srcszip", ".apex", ".capex":
Colin Cross4acaea92021-12-10 23:05:02 +0000194 return true
195 }
196 }
197
198 return false
199}
200
201// LicenseMetadataProvider is used to propagate license metadata paths between modules.
Colin Crossbc7d76c2023-12-12 16:39:03 -0800202var LicenseMetadataProvider = blueprint.NewProvider[*LicenseMetadataInfo]()
Colin Cross4acaea92021-12-10 23:05:02 +0000203
204// LicenseMetadataInfo stores the license metadata path for a module.
205type LicenseMetadataInfo struct {
Colin Crossaff21fb2022-01-12 10:57:57 -0800206 LicenseMetadataPath Path
Colin Crossc85750b2022-04-21 12:50:51 -0700207 LicenseMetadataDepSet *DepSet[Path]
Colin Cross4acaea92021-12-10 23:05:02 +0000208}
209
210// licenseAnnotationsFromTag returns the LicenseAnnotations for a tag (if any) converted into
211// a string, or an empty string if there are none.
212func licenseAnnotationsFromTag(tag blueprint.DependencyTag) string {
213 if annoTag, ok := tag.(LicenseAnnotationsDependencyTag); ok {
214 annos := annoTag.LicenseAnnotations()
215 if len(annos) > 0 {
216 annoStrings := make([]string, len(annos))
217 for i, s := range annos {
218 annoStrings[i] = string(s)
219 }
220 return ":" + strings.Join(annoStrings, ",")
221 }
222 }
223 return ""
224}
225
226// LicenseAnnotationsDependencyTag is implemented by dependency tags in order to provide a
227// list of license dependency annotations.
228type LicenseAnnotationsDependencyTag interface {
229 LicenseAnnotations() []LicenseAnnotation
230}
231
232// LicenseAnnotation is an enum of annotations that can be applied to dependencies for propagating
233// license information.
234type LicenseAnnotation string
235
236const (
237 // LicenseAnnotationSharedDependency should be returned by LicenseAnnotations implementations
238 // of dependency tags when the usage of the dependency is dynamic, for example a shared library
239 // linkage for native modules or as a classpath library for java modules.
Colin Crossce564252022-01-12 11:13:32 -0800240 //
241 // Dependency tags that need to always return LicenseAnnotationSharedDependency
242 // can embed LicenseAnnotationSharedDependencyTag to implement LicenseAnnotations.
Colin Cross4acaea92021-12-10 23:05:02 +0000243 LicenseAnnotationSharedDependency LicenseAnnotation = "dynamic"
244
245 // LicenseAnnotationToolchain should be returned by LicenseAnnotations implementations of
246 // dependency tags when the dependency is used as a toolchain.
247 //
248 // Dependency tags that need to always return LicenseAnnotationToolchain
249 // can embed LicenseAnnotationToolchainDependencyTag to implement LicenseAnnotations.
250 LicenseAnnotationToolchain LicenseAnnotation = "toolchain"
251)
252
Colin Crossce564252022-01-12 11:13:32 -0800253// LicenseAnnotationSharedDependencyTag can be embedded in a dependency tag to implement
254// LicenseAnnotations that always returns LicenseAnnotationSharedDependency.
255type LicenseAnnotationSharedDependencyTag struct{}
256
257func (LicenseAnnotationSharedDependencyTag) LicenseAnnotations() []LicenseAnnotation {
258 return []LicenseAnnotation{LicenseAnnotationSharedDependency}
259}
260
Colin Cross4acaea92021-12-10 23:05:02 +0000261// LicenseAnnotationToolchainDependencyTag can be embedded in a dependency tag to implement
262// LicenseAnnotations that always returns LicenseAnnotationToolchain.
263type LicenseAnnotationToolchainDependencyTag struct{}
264
265func (LicenseAnnotationToolchainDependencyTag) LicenseAnnotations() []LicenseAnnotation {
266 return []LicenseAnnotation{LicenseAnnotationToolchain}
267}