blob: 3df36e674e69c6dca082d0d406e25e0d4a584396 [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 Crossa14fb6a2024-10-23 16:57:06 -070018 "github.com/google/blueprint/depset"
Colin Cross4acaea92021-12-10 23:05:02 +000019 "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
Yu Liuddc28332024-08-09 22:48:30 +000037func buildLicenseMetadata(ctx *moduleContext, licenseMetadataFile WritablePath) {
Colin Cross4acaea92021-12-10 23:05:02 +000038 base := ctx.Module().base()
39
Cole Fausta963b942024-04-11 17:43:00 -070040 if !base.Enabled(ctx) {
Colin Cross4acaea92021-12-10 23:05:02 +000041 return
42 }
43
44 if exemptFromRequiredApplicableLicensesProperty(ctx.Module()) {
45 return
46 }
47
Colin Crossaff21fb2022-01-12 10:57:57 -080048 var outputFiles Paths
mrziwang01201ed2024-07-11 10:21:57 -070049 if outputFiles, err := outputFilesForModule(ctx, ctx.Module(), ""); err == nil {
Colin Crossaff21fb2022-01-12 10:57:57 -080050 outputFiles = PathsIfNonNil(outputFiles...)
51 }
52
Colin Cross5c1d5fb2023-11-15 12:39:40 -080053 // Only pass the last installed file to isContainerFromFileExtensions so a *.zip file in test data
54 // doesn't mark the whole module as a container.
55 var installFiles InstallPaths
Yu Liuddc28332024-08-09 22:48:30 +000056 if len(ctx.installFiles) > 0 {
57 installFiles = InstallPaths{ctx.installFiles[len(ctx.installFiles)-1]}
Colin Cross5c1d5fb2023-11-15 12:39:40 -080058 }
59
60 isContainer := isContainerFromFileExtensions(installFiles, outputFiles)
Colin Crossaff21fb2022-01-12 10:57:57 -080061
Colin Cross4acaea92021-12-10 23:05:02 +000062 var allDepMetadataFiles Paths
63 var allDepMetadataArgs []string
64 var allDepOutputFiles Paths
Colin Crossa14fb6a2024-10-23 16:57:06 -070065 var allDepMetadataDepSets []depset.DepSet[Path]
Colin Cross4acaea92021-12-10 23:05:02 +000066
Colin Cross648daea2024-09-12 14:35:29 -070067 ctx.VisitDirectDeps(func(dep Module) {
Cole Fausta963b942024-04-11 17:43:00 -070068 if !dep.Enabled(ctx) {
Colin Cross4acaea92021-12-10 23:05:02 +000069 return
70 }
71
Bob Badour7fd521e2022-07-29 11:18:12 -070072 // Defaults add properties and dependencies that get processed on their own.
73 if ctx.OtherModuleDependencyTag(dep) == DefaultsDepTag {
74 return
75 }
Jiyong Park8bcf3c62024-03-18 18:37:10 +090076 // The required dependencies just say modules A and B should be installed together.
77 // It doesn't mean that one is built using the other.
78 if ctx.OtherModuleDependencyTag(dep) == RequiredDepTag {
79 return
80 }
Bob Badour7fd521e2022-07-29 11:18:12 -070081
Colin Cross313aa542023-12-13 13:47:44 -080082 if info, ok := OtherModuleProvider(ctx, dep, LicenseMetadataProvider); ok {
Colin Cross4acaea92021-12-10 23:05:02 +000083 allDepMetadataFiles = append(allDepMetadataFiles, info.LicenseMetadataPath)
Colin Crossbd3a16b2023-04-25 11:30:51 -070084 if isContainer || isInstallDepNeeded(dep, ctx.OtherModuleDependencyTag(dep)) {
Colin Crossaff21fb2022-01-12 10:57:57 -080085 allDepMetadataDepSets = append(allDepMetadataDepSets, info.LicenseMetadataDepSet)
86 }
Colin Cross4acaea92021-12-10 23:05:02 +000087
88 depAnnotations := licenseAnnotationsFromTag(ctx.OtherModuleDependencyTag(dep))
89
90 allDepMetadataArgs = append(allDepMetadataArgs, info.LicenseMetadataPath.String()+depAnnotations)
91
Yu Liud46e5ae2024-08-15 18:46:17 +000092 if depInstallFiles := OtherModuleProviderOrDefault(ctx, dep, InstallFilesProvider).InstallFiles; len(depInstallFiles) > 0 {
Colin Cross4acaea92021-12-10 23:05:02 +000093 allDepOutputFiles = append(allDepOutputFiles, depInstallFiles.Paths()...)
94 } else if depOutputFiles, err := outputFilesForModule(ctx, dep, ""); err == nil {
95 depOutputFiles = PathsIfNonNil(depOutputFiles...)
96 allDepOutputFiles = append(allDepOutputFiles, depOutputFiles...)
97 }
98 }
99 })
100
101 allDepMetadataFiles = SortedUniquePaths(allDepMetadataFiles)
102 sort.Strings(allDepMetadataArgs)
103 allDepOutputFiles = SortedUniquePaths(allDepOutputFiles)
104
105 var orderOnlyDeps Paths
106 var args []string
107
Ibrahim Kanouche49920782022-10-13 18:37:24 +0000108 if n := ctx.ModuleName(); n != "" {
109 args = append(args,
110 "-mn "+proptools.NinjaAndShellEscape(n))
111 }
112
Colin Cross4acaea92021-12-10 23:05:02 +0000113 if t := ctx.ModuleType(); t != "" {
114 args = append(args,
115 "-mt "+proptools.NinjaAndShellEscape(t))
116 }
117
118 args = append(args,
119 "-r "+proptools.NinjaAndShellEscape(ctx.ModuleDir()),
120 "-mc UNKNOWN")
121
122 if p := base.commonProperties.Effective_package_name; p != nil {
123 args = append(args,
Bob Badoura10d5a22022-06-21 11:12:01 -0700124 `-p `+proptools.NinjaAndShellEscapeIncludingSpaces(*p))
Colin Cross4acaea92021-12-10 23:05:02 +0000125 }
126
127 args = append(args,
128 JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(base.commonProperties.Effective_license_kinds), "-k "))
129
130 args = append(args,
131 JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(base.commonProperties.Effective_license_conditions), "-c "))
132
133 args = append(args,
134 JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(base.commonProperties.Effective_license_text.Strings()), "-n "))
135
Colin Crossaff21fb2022-01-12 10:57:57 -0800136 if isContainer {
Colin Crossa14fb6a2024-10-23 16:57:06 -0700137 transitiveDeps := Paths(depset.New[Path](depset.TOPOLOGICAL, nil, allDepMetadataDepSets).ToList())
Colin Crossaff21fb2022-01-12 10:57:57 -0800138 args = append(args,
Colin Crossaa1cab02022-01-28 14:49:24 -0800139 JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(transitiveDeps.Strings()), "-d "))
140 orderOnlyDeps = append(orderOnlyDeps, transitiveDeps...)
Colin Crossaff21fb2022-01-12 10:57:57 -0800141 } else {
142 args = append(args,
143 JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(allDepMetadataArgs), "-d "))
144 orderOnlyDeps = append(orderOnlyDeps, allDepMetadataFiles...)
145 }
Colin Cross4acaea92021-12-10 23:05:02 +0000146
147 args = append(args,
148 JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(allDepOutputFiles.Strings()), "-s "))
149
150 // Install map
151 args = append(args,
Yu Liubad1eef2024-08-21 22:37:35 +0000152 JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(ctx.licenseInstallMap), "-m "))
Colin Cross4acaea92021-12-10 23:05:02 +0000153
154 // Built files
Colin Cross4acaea92021-12-10 23:05:02 +0000155 if len(outputFiles) > 0 {
156 args = append(args,
157 JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(outputFiles.Strings()), "-t "))
Colin Cross4acaea92021-12-10 23:05:02 +0000158 }
159
160 // Installed files
161 args = append(args,
Yu Liuddc28332024-08-09 22:48:30 +0000162 JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(ctx.installFiles.Strings()), "-i "))
Colin Cross4acaea92021-12-10 23:05:02 +0000163
Colin Cross4acaea92021-12-10 23:05:02 +0000164 if isContainer {
165 args = append(args, "--is_container")
166 }
167
Colin Cross4acaea92021-12-10 23:05:02 +0000168 ctx.Build(pctx, BuildParams{
169 Rule: licenseMetadataRule,
170 Output: licenseMetadataFile,
171 OrderOnly: orderOnlyDeps,
172 Description: "license metadata",
173 Args: map[string]string{
174 "args": strings.Join(args, " "),
175 },
176 })
177
Colin Cross40213022023-12-13 15:19:49 -0800178 SetProvider(ctx, LicenseMetadataProvider, &LicenseMetadataInfo{
Colin Crossaff21fb2022-01-12 10:57:57 -0800179 LicenseMetadataPath: licenseMetadataFile,
Colin Crossa14fb6a2024-10-23 16:57:06 -0700180 LicenseMetadataDepSet: depset.New(depset.TOPOLOGICAL, Paths{licenseMetadataFile}, allDepMetadataDepSets),
Colin Cross4acaea92021-12-10 23:05:02 +0000181 })
182}
183
184func isContainerFromFileExtensions(installPaths InstallPaths, builtPaths Paths) bool {
185 var paths Paths
186 if len(installPaths) > 0 {
187 paths = installPaths.Paths()
188 } else {
189 paths = builtPaths
190 }
191
192 for _, path := range paths {
193 switch path.Ext() {
Jooyung Han4191da72024-05-03 11:41:11 +0900194 case ".zip", ".tar", ".tgz", ".tar.gz", ".img", ".srcszip", ".apex", ".capex":
Colin Cross4acaea92021-12-10 23:05:02 +0000195 return true
196 }
197 }
198
199 return false
200}
201
202// LicenseMetadataProvider is used to propagate license metadata paths between modules.
Colin Crossbc7d76c2023-12-12 16:39:03 -0800203var LicenseMetadataProvider = blueprint.NewProvider[*LicenseMetadataInfo]()
Colin Cross4acaea92021-12-10 23:05:02 +0000204
205// LicenseMetadataInfo stores the license metadata path for a module.
206type LicenseMetadataInfo struct {
Colin Crossaff21fb2022-01-12 10:57:57 -0800207 LicenseMetadataPath Path
Colin Crossa14fb6a2024-10-23 16:57:06 -0700208 LicenseMetadataDepSet depset.DepSet[Path]
Colin Cross4acaea92021-12-10 23:05:02 +0000209}
210
211// licenseAnnotationsFromTag returns the LicenseAnnotations for a tag (if any) converted into
212// a string, or an empty string if there are none.
213func licenseAnnotationsFromTag(tag blueprint.DependencyTag) string {
214 if annoTag, ok := tag.(LicenseAnnotationsDependencyTag); ok {
215 annos := annoTag.LicenseAnnotations()
216 if len(annos) > 0 {
217 annoStrings := make([]string, len(annos))
218 for i, s := range annos {
219 annoStrings[i] = string(s)
220 }
221 return ":" + strings.Join(annoStrings, ",")
222 }
223 }
224 return ""
225}
226
227// LicenseAnnotationsDependencyTag is implemented by dependency tags in order to provide a
228// list of license dependency annotations.
229type LicenseAnnotationsDependencyTag interface {
230 LicenseAnnotations() []LicenseAnnotation
231}
232
233// LicenseAnnotation is an enum of annotations that can be applied to dependencies for propagating
234// license information.
235type LicenseAnnotation string
236
237const (
238 // LicenseAnnotationSharedDependency should be returned by LicenseAnnotations implementations
239 // of dependency tags when the usage of the dependency is dynamic, for example a shared library
240 // linkage for native modules or as a classpath library for java modules.
Colin Crossce564252022-01-12 11:13:32 -0800241 //
242 // Dependency tags that need to always return LicenseAnnotationSharedDependency
243 // can embed LicenseAnnotationSharedDependencyTag to implement LicenseAnnotations.
Colin Cross4acaea92021-12-10 23:05:02 +0000244 LicenseAnnotationSharedDependency LicenseAnnotation = "dynamic"
245
246 // LicenseAnnotationToolchain should be returned by LicenseAnnotations implementations of
247 // dependency tags when the dependency is used as a toolchain.
248 //
249 // Dependency tags that need to always return LicenseAnnotationToolchain
250 // can embed LicenseAnnotationToolchainDependencyTag to implement LicenseAnnotations.
251 LicenseAnnotationToolchain LicenseAnnotation = "toolchain"
252)
253
Colin Crossce564252022-01-12 11:13:32 -0800254// LicenseAnnotationSharedDependencyTag can be embedded in a dependency tag to implement
255// LicenseAnnotations that always returns LicenseAnnotationSharedDependency.
256type LicenseAnnotationSharedDependencyTag struct{}
257
258func (LicenseAnnotationSharedDependencyTag) LicenseAnnotations() []LicenseAnnotation {
259 return []LicenseAnnotation{LicenseAnnotationSharedDependency}
260}
261
Colin Cross4acaea92021-12-10 23:05:02 +0000262// LicenseAnnotationToolchainDependencyTag can be embedded in a dependency tag to implement
263// LicenseAnnotations that always returns LicenseAnnotationToolchain.
264type LicenseAnnotationToolchainDependencyTag struct{}
265
266func (LicenseAnnotationToolchainDependencyTag) LicenseAnnotations() []LicenseAnnotation {
267 return []LicenseAnnotation{LicenseAnnotationToolchain}
268}