blob: 4ee5bf7ae98554daebe5f48076089c6ac4af92db [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 Crossaff21fb2022-01-12 10:57:57 -080077 if isContainer || IsInstallDepNeeded(ctx.OtherModuleDependencyTag(dep)) {
78 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
101 if t := ctx.ModuleType(); t != "" {
102 args = append(args,
103 "-mt "+proptools.NinjaAndShellEscape(t))
104 }
105
106 args = append(args,
107 "-r "+proptools.NinjaAndShellEscape(ctx.ModuleDir()),
108 "-mc UNKNOWN")
109
110 if p := base.commonProperties.Effective_package_name; p != nil {
111 args = append(args,
Bob Badoura10d5a22022-06-21 11:12:01 -0700112 `-p `+proptools.NinjaAndShellEscapeIncludingSpaces(*p))
Colin Cross4acaea92021-12-10 23:05:02 +0000113 }
114
115 args = append(args,
116 JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(base.commonProperties.Effective_license_kinds), "-k "))
117
118 args = append(args,
119 JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(base.commonProperties.Effective_license_conditions), "-c "))
120
121 args = append(args,
122 JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(base.commonProperties.Effective_license_text.Strings()), "-n "))
123
Colin Crossaff21fb2022-01-12 10:57:57 -0800124 if isContainer {
Colin Crossaa1cab02022-01-28 14:49:24 -0800125 transitiveDeps := newPathsDepSet(nil, allDepMetadataDepSets).ToList()
Colin Crossaff21fb2022-01-12 10:57:57 -0800126 args = append(args,
Colin Crossaa1cab02022-01-28 14:49:24 -0800127 JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(transitiveDeps.Strings()), "-d "))
128 orderOnlyDeps = append(orderOnlyDeps, transitiveDeps...)
Colin Crossaff21fb2022-01-12 10:57:57 -0800129 } else {
130 args = append(args,
131 JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(allDepMetadataArgs), "-d "))
132 orderOnlyDeps = append(orderOnlyDeps, allDepMetadataFiles...)
133 }
Colin Cross4acaea92021-12-10 23:05:02 +0000134
135 args = append(args,
136 JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(allDepOutputFiles.Strings()), "-s "))
137
138 // Install map
139 args = append(args,
140 JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(base.licenseInstallMap), "-m "))
141
142 // Built files
Colin Cross4acaea92021-12-10 23:05:02 +0000143 if len(outputFiles) > 0 {
144 args = append(args,
145 JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(outputFiles.Strings()), "-t "))
Colin Cross4acaea92021-12-10 23:05:02 +0000146 }
147
148 // Installed files
149 args = append(args,
150 JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(base.installFiles.Strings()), "-i "))
151
Colin Cross4acaea92021-12-10 23:05:02 +0000152 if isContainer {
153 args = append(args, "--is_container")
154 }
155
Colin Cross4acaea92021-12-10 23:05:02 +0000156 ctx.Build(pctx, BuildParams{
157 Rule: licenseMetadataRule,
158 Output: licenseMetadataFile,
159 OrderOnly: orderOnlyDeps,
160 Description: "license metadata",
161 Args: map[string]string{
162 "args": strings.Join(args, " "),
163 },
164 })
165
166 ctx.SetProvider(LicenseMetadataProvider, &LicenseMetadataInfo{
Colin Crossaff21fb2022-01-12 10:57:57 -0800167 LicenseMetadataPath: licenseMetadataFile,
168 LicenseMetadataDepSet: newPathsDepSet(Paths{licenseMetadataFile}, allDepMetadataDepSets),
Colin Cross4acaea92021-12-10 23:05:02 +0000169 })
170}
171
172func isContainerFromFileExtensions(installPaths InstallPaths, builtPaths Paths) bool {
173 var paths Paths
174 if len(installPaths) > 0 {
175 paths = installPaths.Paths()
176 } else {
177 paths = builtPaths
178 }
179
180 for _, path := range paths {
181 switch path.Ext() {
182 case ".zip", ".tar", ".tgz", ".tar.gz", ".img", ".srcszip", ".apex":
183 return true
184 }
185 }
186
187 return false
188}
189
190// LicenseMetadataProvider is used to propagate license metadata paths between modules.
191var LicenseMetadataProvider = blueprint.NewProvider(&LicenseMetadataInfo{})
192
193// LicenseMetadataInfo stores the license metadata path for a module.
194type LicenseMetadataInfo struct {
Colin Crossaff21fb2022-01-12 10:57:57 -0800195 LicenseMetadataPath Path
196 LicenseMetadataDepSet *PathsDepSet
Colin Cross4acaea92021-12-10 23:05:02 +0000197}
198
199// licenseAnnotationsFromTag returns the LicenseAnnotations for a tag (if any) converted into
200// a string, or an empty string if there are none.
201func licenseAnnotationsFromTag(tag blueprint.DependencyTag) string {
202 if annoTag, ok := tag.(LicenseAnnotationsDependencyTag); ok {
203 annos := annoTag.LicenseAnnotations()
204 if len(annos) > 0 {
205 annoStrings := make([]string, len(annos))
206 for i, s := range annos {
207 annoStrings[i] = string(s)
208 }
209 return ":" + strings.Join(annoStrings, ",")
210 }
211 }
212 return ""
213}
214
215// LicenseAnnotationsDependencyTag is implemented by dependency tags in order to provide a
216// list of license dependency annotations.
217type LicenseAnnotationsDependencyTag interface {
218 LicenseAnnotations() []LicenseAnnotation
219}
220
221// LicenseAnnotation is an enum of annotations that can be applied to dependencies for propagating
222// license information.
223type LicenseAnnotation string
224
225const (
226 // LicenseAnnotationSharedDependency should be returned by LicenseAnnotations implementations
227 // of dependency tags when the usage of the dependency is dynamic, for example a shared library
228 // linkage for native modules or as a classpath library for java modules.
Colin Crossce564252022-01-12 11:13:32 -0800229 //
230 // Dependency tags that need to always return LicenseAnnotationSharedDependency
231 // can embed LicenseAnnotationSharedDependencyTag to implement LicenseAnnotations.
Colin Cross4acaea92021-12-10 23:05:02 +0000232 LicenseAnnotationSharedDependency LicenseAnnotation = "dynamic"
233
234 // LicenseAnnotationToolchain should be returned by LicenseAnnotations implementations of
235 // dependency tags when the dependency is used as a toolchain.
236 //
237 // Dependency tags that need to always return LicenseAnnotationToolchain
238 // can embed LicenseAnnotationToolchainDependencyTag to implement LicenseAnnotations.
239 LicenseAnnotationToolchain LicenseAnnotation = "toolchain"
240)
241
Colin Crossce564252022-01-12 11:13:32 -0800242// LicenseAnnotationSharedDependencyTag can be embedded in a dependency tag to implement
243// LicenseAnnotations that always returns LicenseAnnotationSharedDependency.
244type LicenseAnnotationSharedDependencyTag struct{}
245
246func (LicenseAnnotationSharedDependencyTag) LicenseAnnotations() []LicenseAnnotation {
247 return []LicenseAnnotation{LicenseAnnotationSharedDependency}
248}
249
Colin Cross4acaea92021-12-10 23:05:02 +0000250// LicenseAnnotationToolchainDependencyTag can be embedded in a dependency tag to implement
251// LicenseAnnotations that always returns LicenseAnnotationToolchain.
252type LicenseAnnotationToolchainDependencyTag struct{}
253
254func (LicenseAnnotationToolchainDependencyTag) LicenseAnnotations() []LicenseAnnotation {
255 return []LicenseAnnotation{LicenseAnnotationToolchain}
256}