blob: 73000a9fa33462bf781992cac665eafe5e85df71 [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
Colin Crossaa1cab02022-01-28 14:49:24 -080036func buildLicenseMetadata(ctx ModuleContext, licenseMetadataFile WritablePath) {
Colin Cross4acaea92021-12-10 23:05:02 +000037 base := ctx.Module().base()
38
39 if !base.Enabled() {
40 return
41 }
42
43 if exemptFromRequiredApplicableLicensesProperty(ctx.Module()) {
44 return
45 }
46
Colin Crossaff21fb2022-01-12 10:57:57 -080047 var outputFiles Paths
48 if outputFileProducer, ok := ctx.Module().(OutputFileProducer); ok {
49 outputFiles, _ = outputFileProducer.OutputFiles("")
50 outputFiles = PathsIfNonNil(outputFiles...)
51 }
52
53 isContainer := isContainerFromFileExtensions(base.installFiles, outputFiles)
54
Colin Cross4acaea92021-12-10 23:05:02 +000055 var allDepMetadataFiles Paths
56 var allDepMetadataArgs []string
57 var allDepOutputFiles Paths
Colin Crossaff21fb2022-01-12 10:57:57 -080058 var allDepMetadataDepSets []*PathsDepSet
Colin Cross4acaea92021-12-10 23:05:02 +000059
60 ctx.VisitDirectDepsBlueprint(func(bpdep blueprint.Module) {
61 dep, _ := bpdep.(Module)
62 if dep == nil {
63 return
64 }
65 if !dep.Enabled() {
66 return
67 }
68
Bob Badour7fd521e2022-07-29 11:18:12 -070069 // Defaults add properties and dependencies that get processed on their own.
70 if ctx.OtherModuleDependencyTag(dep) == DefaultsDepTag {
71 return
72 }
73
Colin Cross4acaea92021-12-10 23:05:02 +000074 if ctx.OtherModuleHasProvider(dep, LicenseMetadataProvider) {
75 info := ctx.OtherModuleProvider(dep, LicenseMetadataProvider).(*LicenseMetadataInfo)
76 allDepMetadataFiles = append(allDepMetadataFiles, info.LicenseMetadataPath)
Colin Crossbd3a16b2023-04-25 11:30:51 -070077 if isContainer || isInstallDepNeeded(dep, ctx.OtherModuleDependencyTag(dep)) {
Colin Crossaff21fb2022-01-12 10:57:57 -080078 allDepMetadataDepSets = append(allDepMetadataDepSets, info.LicenseMetadataDepSet)
79 }
Colin Cross4acaea92021-12-10 23:05:02 +000080
81 depAnnotations := licenseAnnotationsFromTag(ctx.OtherModuleDependencyTag(dep))
82
83 allDepMetadataArgs = append(allDepMetadataArgs, info.LicenseMetadataPath.String()+depAnnotations)
84
85 if depInstallFiles := dep.base().installFiles; len(depInstallFiles) > 0 {
86 allDepOutputFiles = append(allDepOutputFiles, depInstallFiles.Paths()...)
87 } else if depOutputFiles, err := outputFilesForModule(ctx, dep, ""); err == nil {
88 depOutputFiles = PathsIfNonNil(depOutputFiles...)
89 allDepOutputFiles = append(allDepOutputFiles, depOutputFiles...)
90 }
91 }
92 })
93
94 allDepMetadataFiles = SortedUniquePaths(allDepMetadataFiles)
95 sort.Strings(allDepMetadataArgs)
96 allDepOutputFiles = SortedUniquePaths(allDepOutputFiles)
97
98 var orderOnlyDeps Paths
99 var args []string
100
Ibrahim Kanouche49920782022-10-13 18:37:24 +0000101 if n := ctx.ModuleName(); n != "" {
102 args = append(args,
103 "-mn "+proptools.NinjaAndShellEscape(n))
104 }
105
Colin Cross4acaea92021-12-10 23:05:02 +0000106 if t := ctx.ModuleType(); t != "" {
107 args = append(args,
108 "-mt "+proptools.NinjaAndShellEscape(t))
109 }
110
111 args = append(args,
112 "-r "+proptools.NinjaAndShellEscape(ctx.ModuleDir()),
113 "-mc UNKNOWN")
114
115 if p := base.commonProperties.Effective_package_name; p != nil {
116 args = append(args,
Bob Badoura10d5a22022-06-21 11:12:01 -0700117 `-p `+proptools.NinjaAndShellEscapeIncludingSpaces(*p))
Colin Cross4acaea92021-12-10 23:05:02 +0000118 }
119
120 args = append(args,
121 JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(base.commonProperties.Effective_license_kinds), "-k "))
122
123 args = append(args,
124 JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(base.commonProperties.Effective_license_conditions), "-c "))
125
126 args = append(args,
127 JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(base.commonProperties.Effective_license_text.Strings()), "-n "))
128
Colin Crossaff21fb2022-01-12 10:57:57 -0800129 if isContainer {
Colin Crossaa1cab02022-01-28 14:49:24 -0800130 transitiveDeps := newPathsDepSet(nil, allDepMetadataDepSets).ToList()
Colin Crossaff21fb2022-01-12 10:57:57 -0800131 args = append(args,
Colin Crossaa1cab02022-01-28 14:49:24 -0800132 JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(transitiveDeps.Strings()), "-d "))
133 orderOnlyDeps = append(orderOnlyDeps, transitiveDeps...)
Colin Crossaff21fb2022-01-12 10:57:57 -0800134 } else {
135 args = append(args,
136 JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(allDepMetadataArgs), "-d "))
137 orderOnlyDeps = append(orderOnlyDeps, allDepMetadataFiles...)
138 }
Colin Cross4acaea92021-12-10 23:05:02 +0000139
140 args = append(args,
141 JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(allDepOutputFiles.Strings()), "-s "))
142
143 // Install map
144 args = append(args,
145 JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(base.licenseInstallMap), "-m "))
146
147 // Built files
Colin Cross4acaea92021-12-10 23:05:02 +0000148 if len(outputFiles) > 0 {
149 args = append(args,
150 JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(outputFiles.Strings()), "-t "))
Colin Cross4acaea92021-12-10 23:05:02 +0000151 }
152
153 // Installed files
154 args = append(args,
155 JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(base.installFiles.Strings()), "-i "))
156
Colin Cross4acaea92021-12-10 23:05:02 +0000157 if isContainer {
158 args = append(args, "--is_container")
159 }
160
Colin Cross4acaea92021-12-10 23:05:02 +0000161 ctx.Build(pctx, BuildParams{
162 Rule: licenseMetadataRule,
163 Output: licenseMetadataFile,
164 OrderOnly: orderOnlyDeps,
165 Description: "license metadata",
166 Args: map[string]string{
167 "args": strings.Join(args, " "),
168 },
169 })
170
171 ctx.SetProvider(LicenseMetadataProvider, &LicenseMetadataInfo{
Colin Crossaff21fb2022-01-12 10:57:57 -0800172 LicenseMetadataPath: licenseMetadataFile,
173 LicenseMetadataDepSet: newPathsDepSet(Paths{licenseMetadataFile}, allDepMetadataDepSets),
Colin Cross4acaea92021-12-10 23:05:02 +0000174 })
175}
176
177func isContainerFromFileExtensions(installPaths InstallPaths, builtPaths Paths) bool {
178 var paths Paths
179 if len(installPaths) > 0 {
180 paths = installPaths.Paths()
181 } else {
182 paths = builtPaths
183 }
184
185 for _, path := range paths {
186 switch path.Ext() {
187 case ".zip", ".tar", ".tgz", ".tar.gz", ".img", ".srcszip", ".apex":
188 return true
189 }
190 }
191
192 return false
193}
194
195// LicenseMetadataProvider is used to propagate license metadata paths between modules.
196var LicenseMetadataProvider = blueprint.NewProvider(&LicenseMetadataInfo{})
197
198// LicenseMetadataInfo stores the license metadata path for a module.
199type LicenseMetadataInfo struct {
Colin Crossaff21fb2022-01-12 10:57:57 -0800200 LicenseMetadataPath Path
201 LicenseMetadataDepSet *PathsDepSet
Colin Cross4acaea92021-12-10 23:05:02 +0000202}
203
204// licenseAnnotationsFromTag returns the LicenseAnnotations for a tag (if any) converted into
205// a string, or an empty string if there are none.
206func licenseAnnotationsFromTag(tag blueprint.DependencyTag) string {
207 if annoTag, ok := tag.(LicenseAnnotationsDependencyTag); ok {
208 annos := annoTag.LicenseAnnotations()
209 if len(annos) > 0 {
210 annoStrings := make([]string, len(annos))
211 for i, s := range annos {
212 annoStrings[i] = string(s)
213 }
214 return ":" + strings.Join(annoStrings, ",")
215 }
216 }
217 return ""
218}
219
220// LicenseAnnotationsDependencyTag is implemented by dependency tags in order to provide a
221// list of license dependency annotations.
222type LicenseAnnotationsDependencyTag interface {
223 LicenseAnnotations() []LicenseAnnotation
224}
225
226// LicenseAnnotation is an enum of annotations that can be applied to dependencies for propagating
227// license information.
228type LicenseAnnotation string
229
230const (
231 // LicenseAnnotationSharedDependency should be returned by LicenseAnnotations implementations
232 // of dependency tags when the usage of the dependency is dynamic, for example a shared library
233 // linkage for native modules or as a classpath library for java modules.
Colin Crossce564252022-01-12 11:13:32 -0800234 //
235 // Dependency tags that need to always return LicenseAnnotationSharedDependency
236 // can embed LicenseAnnotationSharedDependencyTag to implement LicenseAnnotations.
Colin Cross4acaea92021-12-10 23:05:02 +0000237 LicenseAnnotationSharedDependency LicenseAnnotation = "dynamic"
238
239 // LicenseAnnotationToolchain should be returned by LicenseAnnotations implementations of
240 // dependency tags when the dependency is used as a toolchain.
241 //
242 // Dependency tags that need to always return LicenseAnnotationToolchain
243 // can embed LicenseAnnotationToolchainDependencyTag to implement LicenseAnnotations.
244 LicenseAnnotationToolchain LicenseAnnotation = "toolchain"
245)
246
Colin Crossce564252022-01-12 11:13:32 -0800247// LicenseAnnotationSharedDependencyTag can be embedded in a dependency tag to implement
248// LicenseAnnotations that always returns LicenseAnnotationSharedDependency.
249type LicenseAnnotationSharedDependencyTag struct{}
250
251func (LicenseAnnotationSharedDependencyTag) LicenseAnnotations() []LicenseAnnotation {
252 return []LicenseAnnotation{LicenseAnnotationSharedDependency}
253}
254
Colin Cross4acaea92021-12-10 23:05:02 +0000255// LicenseAnnotationToolchainDependencyTag can be embedded in a dependency tag to implement
256// LicenseAnnotations that always returns LicenseAnnotationToolchain.
257type LicenseAnnotationToolchainDependencyTag struct{}
258
259func (LicenseAnnotationToolchainDependencyTag) LicenseAnnotations() []LicenseAnnotation {
260 return []LicenseAnnotation{LicenseAnnotationToolchain}
261}