blob: c9e0cdd2f24c7ad22f8a088ff92b1f615f43001f [file] [log] [blame]
Colin Cross014489c2020-06-02 20:09:13 -07001// Copyright 2020 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 java
16
17import (
18 "fmt"
19 "sort"
Colin Cross988dfcc2020-07-16 17:32:17 -070020 "strings"
Colin Cross014489c2020-06-02 20:09:13 -070021
22 "android/soong/android"
23)
24
25type LintProperties struct {
26 // Controls for running Android Lint on the module.
27 Lint struct {
28
29 // If true, run Android Lint on the module. Defaults to true.
30 Enabled *bool
31
32 // Flags to pass to the Android Lint tool.
33 Flags []string
34
35 // Checks that should be treated as fatal.
36 Fatal_checks []string
37
38 // Checks that should be treated as errors.
39 Error_checks []string
40
41 // Checks that should be treated as warnings.
42 Warning_checks []string
43
44 // Checks that should be skipped.
45 Disabled_checks []string
Colin Cross92e4b462020-06-18 15:56:48 -070046
47 // Modules that provide extra lint checks
48 Extra_check_modules []string
Colin Cross014489c2020-06-02 20:09:13 -070049 }
50}
51
52type linter struct {
53 name string
54 manifest android.Path
55 mergedManifest android.Path
56 srcs android.Paths
57 srcJars android.Paths
58 resources android.Paths
59 classpath android.Paths
60 classes android.Path
61 extraLintCheckJars android.Paths
62 test bool
63 library bool
64 minSdkVersion string
65 targetSdkVersion string
66 compileSdkVersion string
67 javaLanguageLevel string
68 kotlinLanguageLevel string
69 outputs lintOutputs
70 properties LintProperties
Colin Crossc0efd1d2020-07-03 11:56:24 -070071
Colin Cross08dca382020-07-21 20:31:17 -070072 reports android.Paths
73
Colin Crossc0efd1d2020-07-03 11:56:24 -070074 buildModuleReportZip bool
Colin Cross014489c2020-06-02 20:09:13 -070075}
76
77type lintOutputs struct {
Colin Cross08dca382020-07-21 20:31:17 -070078 html android.Path
79 text android.Path
80 xml android.Path
Colin Crossc0efd1d2020-07-03 11:56:24 -070081
Colin Cross08dca382020-07-21 20:31:17 -070082 depSets LintDepSets
Colin Crossc0efd1d2020-07-03 11:56:24 -070083}
84
Colin Cross08dca382020-07-21 20:31:17 -070085type lintOutputsIntf interface {
Colin Crossc0efd1d2020-07-03 11:56:24 -070086 lintOutputs() *lintOutputs
87}
88
Colin Cross08dca382020-07-21 20:31:17 -070089type lintDepSetsIntf interface {
90 LintDepSets() LintDepSets
91}
92
93type LintDepSets struct {
94 HTML, Text, XML *android.DepSet
95}
96
97type LintDepSetsBuilder struct {
98 HTML, Text, XML *android.DepSetBuilder
99}
100
101func NewLintDepSetBuilder() LintDepSetsBuilder {
102 return LintDepSetsBuilder{
103 HTML: android.NewDepSetBuilder(android.POSTORDER),
104 Text: android.NewDepSetBuilder(android.POSTORDER),
105 XML: android.NewDepSetBuilder(android.POSTORDER),
106 }
107}
108
109func (l LintDepSetsBuilder) Direct(html, text, xml android.Path) LintDepSetsBuilder {
110 l.HTML.Direct(html)
111 l.Text.Direct(text)
112 l.XML.Direct(xml)
113 return l
114}
115
116func (l LintDepSetsBuilder) Transitive(depSets LintDepSets) LintDepSetsBuilder {
117 if depSets.HTML != nil {
118 l.HTML.Transitive(depSets.HTML)
119 }
120 if depSets.Text != nil {
121 l.Text.Transitive(depSets.Text)
122 }
123 if depSets.XML != nil {
124 l.XML.Transitive(depSets.XML)
125 }
126 return l
127}
128
129func (l LintDepSetsBuilder) Build() LintDepSets {
130 return LintDepSets{
131 HTML: l.HTML.Build(),
132 Text: l.Text.Build(),
133 XML: l.XML.Build(),
134 }
135}
136
137func (l *linter) LintDepSets() LintDepSets {
138 return l.outputs.depSets
139}
140
141var _ lintDepSetsIntf = (*linter)(nil)
142
143var _ lintOutputsIntf = (*linter)(nil)
Colin Crossc0efd1d2020-07-03 11:56:24 -0700144
145func (l *linter) lintOutputs() *lintOutputs {
146 return &l.outputs
Colin Cross014489c2020-06-02 20:09:13 -0700147}
148
149func (l *linter) enabled() bool {
150 return BoolDefault(l.properties.Lint.Enabled, true)
151}
152
Colin Cross92e4b462020-06-18 15:56:48 -0700153func (l *linter) deps(ctx android.BottomUpMutatorContext) {
154 if !l.enabled() {
155 return
156 }
157
Colin Cross988dfcc2020-07-16 17:32:17 -0700158 extraCheckModules := l.properties.Lint.Extra_check_modules
159
160 if checkOnly := ctx.Config().Getenv("ANDROID_LINT_CHECK"); checkOnly != "" {
161 if checkOnlyModules := ctx.Config().Getenv("ANDROID_LINT_CHECK_EXTRA_MODULES"); checkOnlyModules != "" {
162 extraCheckModules = strings.Split(checkOnlyModules, ",")
163 }
164 }
165
166 ctx.AddFarVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(),
167 extraLintCheckTag, extraCheckModules...)
Colin Cross92e4b462020-06-18 15:56:48 -0700168}
169
Colin Cross014489c2020-06-02 20:09:13 -0700170func (l *linter) writeLintProjectXML(ctx android.ModuleContext,
Colin Cross977b6a82020-06-23 10:22:49 -0700171 rule *android.RuleBuilder) (projectXMLPath, configXMLPath, cacheDir, homeDir android.WritablePath, deps android.Paths) {
Colin Cross014489c2020-06-02 20:09:13 -0700172
173 var resourcesList android.WritablePath
174 if len(l.resources) > 0 {
175 // The list of resources may be too long to put on the command line, but
176 // we can't use the rsp file because it is already being used for srcs.
177 // Insert a second rule to write out the list of resources to a file.
178 resourcesList = android.PathForModuleOut(ctx, "lint", "resources.list")
Colin Crossf1a035e2020-11-16 17:32:30 -0800179 resListRule := android.NewRuleBuilder(pctx, ctx)
Colin Cross014489c2020-06-02 20:09:13 -0700180 resListRule.Command().Text("cp").FlagWithRspFileInputList("", l.resources).Output(resourcesList)
Colin Crossf1a035e2020-11-16 17:32:30 -0800181 resListRule.Build("lint_resources_list", "lint resources list")
Colin Cross014489c2020-06-02 20:09:13 -0700182 deps = append(deps, l.resources...)
183 }
184
185 projectXMLPath = android.PathForModuleOut(ctx, "lint", "project.xml")
186 // Lint looks for a lint.xml file next to the project.xml file, give it one.
187 configXMLPath = android.PathForModuleOut(ctx, "lint", "lint.xml")
188 cacheDir = android.PathForModuleOut(ctx, "lint", "cache")
Colin Cross977b6a82020-06-23 10:22:49 -0700189 homeDir = android.PathForModuleOut(ctx, "lint", "home")
Colin Cross014489c2020-06-02 20:09:13 -0700190
191 srcJarDir := android.PathForModuleOut(ctx, "lint-srcjars")
192 srcJarList := zipSyncCmd(ctx, rule, srcJarDir, l.srcJars)
193
194 cmd := rule.Command().
Colin Crossf1a035e2020-11-16 17:32:30 -0800195 BuiltTool("lint-project-xml").
Colin Cross014489c2020-06-02 20:09:13 -0700196 FlagWithOutput("--project_out ", projectXMLPath).
197 FlagWithOutput("--config_out ", configXMLPath).
198 FlagWithArg("--name ", ctx.ModuleName())
199
200 if l.library {
201 cmd.Flag("--library")
202 }
203 if l.test {
204 cmd.Flag("--test")
205 }
206 if l.manifest != nil {
207 deps = append(deps, l.manifest)
208 cmd.FlagWithArg("--manifest ", l.manifest.String())
209 }
210 if l.mergedManifest != nil {
211 deps = append(deps, l.mergedManifest)
212 cmd.FlagWithArg("--merged_manifest ", l.mergedManifest.String())
213 }
214
215 // TODO(ccross): some of the files in l.srcs are generated sources and should be passed to
216 // lint separately.
217 cmd.FlagWithRspFileInputList("--srcs ", l.srcs)
218 deps = append(deps, l.srcs...)
219
220 cmd.FlagWithInput("--generated_srcs ", srcJarList)
221 deps = append(deps, l.srcJars...)
222
223 if resourcesList != nil {
224 cmd.FlagWithInput("--resources ", resourcesList)
225 }
226
227 if l.classes != nil {
228 deps = append(deps, l.classes)
229 cmd.FlagWithArg("--classes ", l.classes.String())
230 }
231
232 cmd.FlagForEachArg("--classpath ", l.classpath.Strings())
233 deps = append(deps, l.classpath...)
234
235 cmd.FlagForEachArg("--extra_checks_jar ", l.extraLintCheckJars.Strings())
236 deps = append(deps, l.extraLintCheckJars...)
237
Colin Crossc31efeb2020-06-23 10:25:26 -0700238 cmd.FlagWithArg("--root_dir ", "$PWD")
239
240 // The cache tag in project.xml is relative to the root dir, or the project.xml file if
241 // the root dir is not set.
242 cmd.FlagWithArg("--cache_dir ", cacheDir.String())
Colin Cross014489c2020-06-02 20:09:13 -0700243
244 cmd.FlagWithInput("@",
245 android.PathForSource(ctx, "build/soong/java/lint_defaults.txt"))
246
247 cmd.FlagForEachArg("--disable_check ", l.properties.Lint.Disabled_checks)
248 cmd.FlagForEachArg("--warning_check ", l.properties.Lint.Warning_checks)
249 cmd.FlagForEachArg("--error_check ", l.properties.Lint.Error_checks)
250 cmd.FlagForEachArg("--fatal_check ", l.properties.Lint.Fatal_checks)
251
Colin Cross977b6a82020-06-23 10:22:49 -0700252 return projectXMLPath, configXMLPath, cacheDir, homeDir, deps
Colin Cross014489c2020-06-02 20:09:13 -0700253}
254
Liz Kammer20ebfb42020-07-28 11:32:07 -0700255// generateManifest adds a command to the rule to write a simple manifest that contains the
Colin Cross014489c2020-06-02 20:09:13 -0700256// minSdkVersion and targetSdkVersion for modules (like java_library) that don't have a manifest.
257func (l *linter) generateManifest(ctx android.ModuleContext, rule *android.RuleBuilder) android.Path {
258 manifestPath := android.PathForModuleOut(ctx, "lint", "AndroidManifest.xml")
259
260 rule.Command().Text("(").
261 Text(`echo "<?xml version='1.0' encoding='utf-8'?>" &&`).
262 Text(`echo "<manifest xmlns:android='http://schemas.android.com/apk/res/android'" &&`).
263 Text(`echo " android:versionCode='1' android:versionName='1' >" &&`).
264 Textf(`echo " <uses-sdk android:minSdkVersion='%s' android:targetSdkVersion='%s'/>" &&`,
265 l.minSdkVersion, l.targetSdkVersion).
266 Text(`echo "</manifest>"`).
267 Text(") >").Output(manifestPath)
268
269 return manifestPath
270}
271
272func (l *linter) lint(ctx android.ModuleContext) {
273 if !l.enabled() {
274 return
275 }
276
Colin Cross92e4b462020-06-18 15:56:48 -0700277 extraLintCheckModules := ctx.GetDirectDepsWithTag(extraLintCheckTag)
278 for _, extraLintCheckModule := range extraLintCheckModules {
Colin Crossdcf71b22021-02-01 13:59:03 -0800279 if ctx.OtherModuleHasProvider(extraLintCheckModule, JavaInfoProvider) {
280 dep := ctx.OtherModuleProvider(extraLintCheckModule, JavaInfoProvider).(JavaInfo)
281 l.extraLintCheckJars = append(l.extraLintCheckJars, dep.ImplementationAndResourcesJars...)
Colin Cross92e4b462020-06-18 15:56:48 -0700282 } else {
283 ctx.PropertyErrorf("lint.extra_check_modules",
284 "%s is not a java module", ctx.OtherModuleName(extraLintCheckModule))
285 }
286 }
287
Colin Crossf1a035e2020-11-16 17:32:30 -0800288 rule := android.NewRuleBuilder(pctx, ctx)
Colin Cross014489c2020-06-02 20:09:13 -0700289
290 if l.manifest == nil {
291 manifest := l.generateManifest(ctx, rule)
292 l.manifest = manifest
293 }
294
Colin Cross977b6a82020-06-23 10:22:49 -0700295 projectXML, lintXML, cacheDir, homeDir, deps := l.writeLintProjectXML(ctx, rule)
Colin Cross014489c2020-06-02 20:09:13 -0700296
Colin Crossc0efd1d2020-07-03 11:56:24 -0700297 html := android.PathForModuleOut(ctx, "lint-report.html")
298 text := android.PathForModuleOut(ctx, "lint-report.txt")
299 xml := android.PathForModuleOut(ctx, "lint-report.xml")
300
Colin Cross08dca382020-07-21 20:31:17 -0700301 depSetsBuilder := NewLintDepSetBuilder().Direct(html, text, xml)
Colin Crossc0efd1d2020-07-03 11:56:24 -0700302
303 ctx.VisitDirectDepsWithTag(staticLibTag, func(dep android.Module) {
Colin Cross08dca382020-07-21 20:31:17 -0700304 if depLint, ok := dep.(lintDepSetsIntf); ok {
305 depSetsBuilder.Transitive(depLint.LintDepSets())
Colin Crossc0efd1d2020-07-03 11:56:24 -0700306 }
307 })
Colin Cross014489c2020-06-02 20:09:13 -0700308
Colin Cross977b6a82020-06-23 10:22:49 -0700309 rule.Command().Text("rm -rf").Flag(cacheDir.String()).Flag(homeDir.String())
310 rule.Command().Text("mkdir -p").Flag(cacheDir.String()).Flag(homeDir.String())
Colin Cross014489c2020-06-02 20:09:13 -0700311
Colin Cross8a6ed372020-07-06 11:45:51 -0700312 var annotationsZipPath, apiVersionsXMLPath android.Path
Jeongik Cha816a23a2020-07-08 01:09:23 +0900313 if ctx.Config().AlwaysUsePrebuiltSdks() {
Colin Cross8a6ed372020-07-06 11:45:51 -0700314 annotationsZipPath = android.PathForSource(ctx, "prebuilts/sdk/current/public/data/annotations.zip")
315 apiVersionsXMLPath = android.PathForSource(ctx, "prebuilts/sdk/current/public/data/api-versions.xml")
316 } else {
317 annotationsZipPath = copiedAnnotationsZipPath(ctx)
318 apiVersionsXMLPath = copiedAPIVersionsXmlPath(ctx)
319 }
320
Colin Cross988dfcc2020-07-16 17:32:17 -0700321 cmd := rule.Command().
Colin Cross014489c2020-06-02 20:09:13 -0700322 Text("(").
Colin Crosse2221792020-07-13 13:23:00 -0700323 Flag("JAVA_OPTS=-Xmx3072m").
Colin Cross977b6a82020-06-23 10:22:49 -0700324 FlagWithArg("ANDROID_SDK_HOME=", homeDir.String()).
Colin Cross8a6ed372020-07-06 11:45:51 -0700325 FlagWithInput("SDK_ANNOTATIONS=", annotationsZipPath).
326 FlagWithInput("LINT_OPTS=-DLINT_API_DATABASE=", apiVersionsXMLPath).
Colin Cross014489c2020-06-02 20:09:13 -0700327 Tool(android.PathForSource(ctx, "prebuilts/cmdline-tools/tools/bin/lint")).
328 Implicit(android.PathForSource(ctx, "prebuilts/cmdline-tools/tools/lib/lint-classpath.jar")).
329 Flag("--quiet").
330 FlagWithInput("--project ", projectXML).
331 FlagWithInput("--config ", lintXML).
Colin Crossc0efd1d2020-07-03 11:56:24 -0700332 FlagWithOutput("--html ", html).
333 FlagWithOutput("--text ", text).
334 FlagWithOutput("--xml ", xml).
Colin Cross014489c2020-06-02 20:09:13 -0700335 FlagWithArg("--compile-sdk-version ", l.compileSdkVersion).
336 FlagWithArg("--java-language-level ", l.javaLanguageLevel).
337 FlagWithArg("--kotlin-language-level ", l.kotlinLanguageLevel).
338 FlagWithArg("--url ", fmt.Sprintf(".=.,%s=out", android.PathForOutput(ctx).String())).
339 Flag("--exitcode").
340 Flags(l.properties.Lint.Flags).
Colin Cross988dfcc2020-07-16 17:32:17 -0700341 Implicits(deps)
342
343 if checkOnly := ctx.Config().Getenv("ANDROID_LINT_CHECK"); checkOnly != "" {
344 cmd.FlagWithArg("--check ", checkOnly)
345 }
346
347 cmd.Text("|| (").Text("cat").Input(text).Text("; exit 7)").Text(")")
Colin Cross014489c2020-06-02 20:09:13 -0700348
Colin Cross977b6a82020-06-23 10:22:49 -0700349 rule.Command().Text("rm -rf").Flag(cacheDir.String()).Flag(homeDir.String())
Colin Cross014489c2020-06-02 20:09:13 -0700350
Colin Crossf1a035e2020-11-16 17:32:30 -0800351 rule.Build("lint", "lint")
Colin Cross014489c2020-06-02 20:09:13 -0700352
Colin Crossc0efd1d2020-07-03 11:56:24 -0700353 l.outputs = lintOutputs{
354 html: html,
355 text: text,
356 xml: xml,
Colin Cross014489c2020-06-02 20:09:13 -0700357
Colin Cross08dca382020-07-21 20:31:17 -0700358 depSets: depSetsBuilder.Build(),
Colin Crossc0efd1d2020-07-03 11:56:24 -0700359 }
Colin Cross014489c2020-06-02 20:09:13 -0700360
Colin Crossc0efd1d2020-07-03 11:56:24 -0700361 if l.buildModuleReportZip {
Colin Cross08dca382020-07-21 20:31:17 -0700362 l.reports = BuildModuleLintReportZips(ctx, l.LintDepSets())
Colin Crossc0efd1d2020-07-03 11:56:24 -0700363 }
364}
Colin Cross014489c2020-06-02 20:09:13 -0700365
Colin Cross08dca382020-07-21 20:31:17 -0700366func BuildModuleLintReportZips(ctx android.ModuleContext, depSets LintDepSets) android.Paths {
367 htmlList := depSets.HTML.ToSortedList()
368 textList := depSets.Text.ToSortedList()
369 xmlList := depSets.XML.ToSortedList()
370
371 if len(htmlList) == 0 && len(textList) == 0 && len(xmlList) == 0 {
372 return nil
373 }
374
375 htmlZip := android.PathForModuleOut(ctx, "lint-report-html.zip")
376 lintZip(ctx, htmlList, htmlZip)
377
378 textZip := android.PathForModuleOut(ctx, "lint-report-text.zip")
379 lintZip(ctx, textList, textZip)
380
381 xmlZip := android.PathForModuleOut(ctx, "lint-report-xml.zip")
382 lintZip(ctx, xmlList, xmlZip)
383
384 return android.Paths{htmlZip, textZip, xmlZip}
385}
386
Colin Cross014489c2020-06-02 20:09:13 -0700387type lintSingleton struct {
388 htmlZip android.WritablePath
389 textZip android.WritablePath
390 xmlZip android.WritablePath
391}
392
393func (l *lintSingleton) GenerateBuildActions(ctx android.SingletonContext) {
394 l.generateLintReportZips(ctx)
395 l.copyLintDependencies(ctx)
396}
397
398func (l *lintSingleton) copyLintDependencies(ctx android.SingletonContext) {
Jeongik Cha816a23a2020-07-08 01:09:23 +0900399 if ctx.Config().AlwaysUsePrebuiltSdks() {
Colin Cross014489c2020-06-02 20:09:13 -0700400 return
401 }
402
403 var frameworkDocStubs android.Module
404 ctx.VisitAllModules(func(m android.Module) {
405 if ctx.ModuleName(m) == "framework-doc-stubs" {
406 if frameworkDocStubs == nil {
407 frameworkDocStubs = m
408 } else {
409 ctx.Errorf("lint: multiple framework-doc-stubs modules found: %s and %s",
410 ctx.ModuleSubDir(m), ctx.ModuleSubDir(frameworkDocStubs))
411 }
412 }
413 })
414
415 if frameworkDocStubs == nil {
416 if !ctx.Config().AllowMissingDependencies() {
417 ctx.Errorf("lint: missing framework-doc-stubs")
418 }
419 return
420 }
421
422 ctx.Build(pctx, android.BuildParams{
423 Rule: android.Cp,
424 Input: android.OutputFileForModule(ctx, frameworkDocStubs, ".annotations.zip"),
Colin Cross8a6ed372020-07-06 11:45:51 -0700425 Output: copiedAnnotationsZipPath(ctx),
Colin Cross014489c2020-06-02 20:09:13 -0700426 })
427
428 ctx.Build(pctx, android.BuildParams{
429 Rule: android.Cp,
430 Input: android.OutputFileForModule(ctx, frameworkDocStubs, ".api_versions.xml"),
Colin Cross8a6ed372020-07-06 11:45:51 -0700431 Output: copiedAPIVersionsXmlPath(ctx),
Colin Cross014489c2020-06-02 20:09:13 -0700432 })
433}
434
Colin Cross8a6ed372020-07-06 11:45:51 -0700435func copiedAnnotationsZipPath(ctx android.PathContext) android.WritablePath {
Colin Cross014489c2020-06-02 20:09:13 -0700436 return android.PathForOutput(ctx, "lint", "annotations.zip")
437}
438
Colin Cross8a6ed372020-07-06 11:45:51 -0700439func copiedAPIVersionsXmlPath(ctx android.PathContext) android.WritablePath {
Colin Cross014489c2020-06-02 20:09:13 -0700440 return android.PathForOutput(ctx, "lint", "api_versions.xml")
441}
442
443func (l *lintSingleton) generateLintReportZips(ctx android.SingletonContext) {
Colin Cross8a6ed372020-07-06 11:45:51 -0700444 if ctx.Config().UnbundledBuild() {
445 return
446 }
447
Colin Cross014489c2020-06-02 20:09:13 -0700448 var outputs []*lintOutputs
449 var dirs []string
450 ctx.VisitAllModules(func(m android.Module) {
Jingwen Chencda22c92020-11-23 00:22:30 -0500451 if ctx.Config().KatiEnabled() && !m.ExportedToMake() {
Colin Cross014489c2020-06-02 20:09:13 -0700452 return
453 }
454
Colin Cross56a83212020-09-15 18:30:11 -0700455 if apex, ok := m.(android.ApexModule); ok && apex.NotAvailableForPlatform() {
456 apexInfo := ctx.ModuleProvider(m, android.ApexInfoProvider).(android.ApexInfo)
457 if apexInfo.IsForPlatform() {
458 // There are stray platform variants of modules in apexes that are not available for
459 // the platform, and they sometimes can't be built. Don't depend on them.
460 return
461 }
Colin Cross014489c2020-06-02 20:09:13 -0700462 }
463
Colin Cross08dca382020-07-21 20:31:17 -0700464 if l, ok := m.(lintOutputsIntf); ok {
Colin Cross014489c2020-06-02 20:09:13 -0700465 outputs = append(outputs, l.lintOutputs())
466 }
467 })
468
469 dirs = android.SortedUniqueStrings(dirs)
470
471 zip := func(outputPath android.WritablePath, get func(*lintOutputs) android.Path) {
472 var paths android.Paths
473
474 for _, output := range outputs {
Colin Cross08dca382020-07-21 20:31:17 -0700475 if p := get(output); p != nil {
476 paths = append(paths, p)
477 }
Colin Cross014489c2020-06-02 20:09:13 -0700478 }
479
Colin Crossc0efd1d2020-07-03 11:56:24 -0700480 lintZip(ctx, paths, outputPath)
Colin Cross014489c2020-06-02 20:09:13 -0700481 }
482
483 l.htmlZip = android.PathForOutput(ctx, "lint-report-html.zip")
484 zip(l.htmlZip, func(l *lintOutputs) android.Path { return l.html })
485
486 l.textZip = android.PathForOutput(ctx, "lint-report-text.zip")
487 zip(l.textZip, func(l *lintOutputs) android.Path { return l.text })
488
489 l.xmlZip = android.PathForOutput(ctx, "lint-report-xml.zip")
490 zip(l.xmlZip, func(l *lintOutputs) android.Path { return l.xml })
491
492 ctx.Phony("lint-check", l.htmlZip, l.textZip, l.xmlZip)
493}
494
495func (l *lintSingleton) MakeVars(ctx android.MakeVarsContext) {
Colin Cross8a6ed372020-07-06 11:45:51 -0700496 if !ctx.Config().UnbundledBuild() {
497 ctx.DistForGoal("lint-check", l.htmlZip, l.textZip, l.xmlZip)
498 }
Colin Cross014489c2020-06-02 20:09:13 -0700499}
500
501var _ android.SingletonMakeVarsProvider = (*lintSingleton)(nil)
502
503func init() {
504 android.RegisterSingletonType("lint",
505 func() android.Singleton { return &lintSingleton{} })
506}
Colin Crossc0efd1d2020-07-03 11:56:24 -0700507
508func lintZip(ctx android.BuilderContext, paths android.Paths, outputPath android.WritablePath) {
509 paths = android.SortedUniquePaths(android.CopyOfPaths(paths))
510
511 sort.Slice(paths, func(i, j int) bool {
512 return paths[i].String() < paths[j].String()
513 })
514
Colin Crossf1a035e2020-11-16 17:32:30 -0800515 rule := android.NewRuleBuilder(pctx, ctx)
Colin Crossc0efd1d2020-07-03 11:56:24 -0700516
Colin Crossf1a035e2020-11-16 17:32:30 -0800517 rule.Command().BuiltTool("soong_zip").
Colin Crossc0efd1d2020-07-03 11:56:24 -0700518 FlagWithOutput("-o ", outputPath).
519 FlagWithArg("-C ", android.PathForIntermediates(ctx).String()).
Colin Cross053fca12020-08-19 13:51:47 -0700520 FlagWithRspFileInputList("-r ", paths)
Colin Crossc0efd1d2020-07-03 11:56:24 -0700521
Colin Crossf1a035e2020-11-16 17:32:30 -0800522 rule.Build(outputPath.Base(), outputPath.Base())
Colin Crossc0efd1d2020-07-03 11:56:24 -0700523}