lint.go 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606
  1. // 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. package java
  15. import (
  16. "fmt"
  17. "sort"
  18. "strings"
  19. "github.com/google/blueprint/proptools"
  20. "android/soong/android"
  21. "android/soong/java/config"
  22. "android/soong/remoteexec"
  23. )
  24. // lint checks automatically enforced for modules that have different min_sdk_version than
  25. // sdk_version
  26. var updatabilityChecks = []string{"NewApi"}
  27. type LintProperties struct {
  28. // Controls for running Android Lint on the module.
  29. Lint struct {
  30. // If true, run Android Lint on the module. Defaults to true.
  31. Enabled *bool
  32. // Flags to pass to the Android Lint tool.
  33. Flags []string
  34. // Checks that should be treated as fatal.
  35. Fatal_checks []string
  36. // Checks that should be treated as errors.
  37. Error_checks []string
  38. // Checks that should be treated as warnings.
  39. Warning_checks []string
  40. // Checks that should be skipped.
  41. Disabled_checks []string
  42. // Modules that provide extra lint checks
  43. Extra_check_modules []string
  44. // Name of the file that lint uses as the baseline. Defaults to "lint-baseline.xml".
  45. Baseline_filename *string
  46. // If true, baselining updatability lint checks (e.g. NewApi) is prohibited. Defaults to false.
  47. Strict_updatability_linting *bool
  48. }
  49. }
  50. type linter struct {
  51. name string
  52. manifest android.Path
  53. mergedManifest android.Path
  54. srcs android.Paths
  55. srcJars android.Paths
  56. resources android.Paths
  57. classpath android.Paths
  58. classes android.Path
  59. extraLintCheckJars android.Paths
  60. test bool
  61. library bool
  62. minSdkVersion string
  63. targetSdkVersion string
  64. compileSdkVersion string
  65. javaLanguageLevel string
  66. kotlinLanguageLevel string
  67. outputs lintOutputs
  68. properties LintProperties
  69. extraMainlineLintErrors []string
  70. reports android.Paths
  71. buildModuleReportZip bool
  72. }
  73. type lintOutputs struct {
  74. html android.Path
  75. text android.Path
  76. xml android.Path
  77. depSets LintDepSets
  78. }
  79. type lintOutputsIntf interface {
  80. lintOutputs() *lintOutputs
  81. }
  82. type lintDepSetsIntf interface {
  83. LintDepSets() LintDepSets
  84. }
  85. type LintDepSets struct {
  86. HTML, Text, XML *android.DepSet
  87. }
  88. type LintDepSetsBuilder struct {
  89. HTML, Text, XML *android.DepSetBuilder
  90. }
  91. func NewLintDepSetBuilder() LintDepSetsBuilder {
  92. return LintDepSetsBuilder{
  93. HTML: android.NewDepSetBuilder(android.POSTORDER),
  94. Text: android.NewDepSetBuilder(android.POSTORDER),
  95. XML: android.NewDepSetBuilder(android.POSTORDER),
  96. }
  97. }
  98. func (l LintDepSetsBuilder) Direct(html, text, xml android.Path) LintDepSetsBuilder {
  99. l.HTML.Direct(html)
  100. l.Text.Direct(text)
  101. l.XML.Direct(xml)
  102. return l
  103. }
  104. func (l LintDepSetsBuilder) Transitive(depSets LintDepSets) LintDepSetsBuilder {
  105. if depSets.HTML != nil {
  106. l.HTML.Transitive(depSets.HTML)
  107. }
  108. if depSets.Text != nil {
  109. l.Text.Transitive(depSets.Text)
  110. }
  111. if depSets.XML != nil {
  112. l.XML.Transitive(depSets.XML)
  113. }
  114. return l
  115. }
  116. func (l LintDepSetsBuilder) Build() LintDepSets {
  117. return LintDepSets{
  118. HTML: l.HTML.Build(),
  119. Text: l.Text.Build(),
  120. XML: l.XML.Build(),
  121. }
  122. }
  123. func (l *linter) LintDepSets() LintDepSets {
  124. return l.outputs.depSets
  125. }
  126. var _ lintDepSetsIntf = (*linter)(nil)
  127. var _ lintOutputsIntf = (*linter)(nil)
  128. func (l *linter) lintOutputs() *lintOutputs {
  129. return &l.outputs
  130. }
  131. func (l *linter) enabled() bool {
  132. return BoolDefault(l.properties.Lint.Enabled, true)
  133. }
  134. func (l *linter) deps(ctx android.BottomUpMutatorContext) {
  135. if !l.enabled() {
  136. return
  137. }
  138. extraCheckModules := l.properties.Lint.Extra_check_modules
  139. if checkOnly := ctx.Config().Getenv("ANDROID_LINT_CHECK"); checkOnly != "" {
  140. if checkOnlyModules := ctx.Config().Getenv("ANDROID_LINT_CHECK_EXTRA_MODULES"); checkOnlyModules != "" {
  141. extraCheckModules = strings.Split(checkOnlyModules, ",")
  142. }
  143. }
  144. ctx.AddFarVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(),
  145. extraLintCheckTag, extraCheckModules...)
  146. }
  147. // lintPaths contains the paths to lint's inputs and outputs to make it easier to pass them
  148. // around.
  149. type lintPaths struct {
  150. projectXML android.WritablePath
  151. configXML android.WritablePath
  152. cacheDir android.WritablePath
  153. homeDir android.WritablePath
  154. srcjarDir android.WritablePath
  155. }
  156. func lintRBEExecStrategy(ctx android.ModuleContext) string {
  157. return ctx.Config().GetenvWithDefault("RBE_LINT_EXEC_STRATEGY", remoteexec.LocalExecStrategy)
  158. }
  159. func (l *linter) writeLintProjectXML(ctx android.ModuleContext, rule *android.RuleBuilder) lintPaths {
  160. projectXMLPath := android.PathForModuleOut(ctx, "lint", "project.xml")
  161. // Lint looks for a lint.xml file next to the project.xml file, give it one.
  162. configXMLPath := android.PathForModuleOut(ctx, "lint", "lint.xml")
  163. cacheDir := android.PathForModuleOut(ctx, "lint", "cache")
  164. homeDir := android.PathForModuleOut(ctx, "lint", "home")
  165. srcJarDir := android.PathForModuleOut(ctx, "lint", "srcjars")
  166. srcJarList := zipSyncCmd(ctx, rule, srcJarDir, l.srcJars)
  167. cmd := rule.Command().
  168. BuiltTool("lint_project_xml").
  169. FlagWithOutput("--project_out ", projectXMLPath).
  170. FlagWithOutput("--config_out ", configXMLPath).
  171. FlagWithArg("--name ", ctx.ModuleName())
  172. if l.library {
  173. cmd.Flag("--library")
  174. }
  175. if l.test {
  176. cmd.Flag("--test")
  177. }
  178. if l.manifest != nil {
  179. cmd.FlagWithInput("--manifest ", l.manifest)
  180. }
  181. if l.mergedManifest != nil {
  182. cmd.FlagWithInput("--merged_manifest ", l.mergedManifest)
  183. }
  184. // TODO(ccross): some of the files in l.srcs are generated sources and should be passed to
  185. // lint separately.
  186. srcsList := android.PathForModuleOut(ctx, "lint-srcs.list")
  187. cmd.FlagWithRspFileInputList("--srcs ", srcsList, l.srcs)
  188. cmd.FlagWithInput("--generated_srcs ", srcJarList)
  189. if len(l.resources) > 0 {
  190. resourcesList := android.PathForModuleOut(ctx, "lint-resources.list")
  191. cmd.FlagWithRspFileInputList("--resources ", resourcesList, l.resources)
  192. }
  193. if l.classes != nil {
  194. cmd.FlagWithInput("--classes ", l.classes)
  195. }
  196. cmd.FlagForEachInput("--classpath ", l.classpath)
  197. cmd.FlagForEachInput("--extra_checks_jar ", l.extraLintCheckJars)
  198. cmd.FlagWithArg("--root_dir ", "$PWD")
  199. // The cache tag in project.xml is relative to the root dir, or the project.xml file if
  200. // the root dir is not set.
  201. cmd.FlagWithArg("--cache_dir ", cacheDir.String())
  202. cmd.FlagWithInput("@",
  203. android.PathForSource(ctx, "build/soong/java/lint_defaults.txt"))
  204. cmd.FlagForEachArg("--error_check ", l.extraMainlineLintErrors)
  205. cmd.FlagForEachArg("--disable_check ", l.properties.Lint.Disabled_checks)
  206. cmd.FlagForEachArg("--warning_check ", l.properties.Lint.Warning_checks)
  207. cmd.FlagForEachArg("--error_check ", l.properties.Lint.Error_checks)
  208. cmd.FlagForEachArg("--fatal_check ", l.properties.Lint.Fatal_checks)
  209. if BoolDefault(l.properties.Lint.Strict_updatability_linting, false) {
  210. // Verify the module does not baseline issues that endanger safe updatability.
  211. if baselinePath := l.getBaselineFilepath(ctx); baselinePath.Valid() {
  212. cmd.FlagWithInput("--baseline ", baselinePath.Path())
  213. cmd.FlagForEachArg("--disallowed_issues ", updatabilityChecks)
  214. }
  215. }
  216. return lintPaths{
  217. projectXML: projectXMLPath,
  218. configXML: configXMLPath,
  219. cacheDir: cacheDir,
  220. homeDir: homeDir,
  221. }
  222. }
  223. // generateManifest adds a command to the rule to write a simple manifest that contains the
  224. // minSdkVersion and targetSdkVersion for modules (like java_library) that don't have a manifest.
  225. func (l *linter) generateManifest(ctx android.ModuleContext, rule *android.RuleBuilder) android.WritablePath {
  226. manifestPath := android.PathForModuleOut(ctx, "lint", "AndroidManifest.xml")
  227. rule.Command().Text("(").
  228. Text(`echo "<?xml version='1.0' encoding='utf-8'?>" &&`).
  229. Text(`echo "<manifest xmlns:android='http://schemas.android.com/apk/res/android'" &&`).
  230. Text(`echo " android:versionCode='1' android:versionName='1' >" &&`).
  231. Textf(`echo " <uses-sdk android:minSdkVersion='%s' android:targetSdkVersion='%s'/>" &&`,
  232. l.minSdkVersion, l.targetSdkVersion).
  233. Text(`echo "</manifest>"`).
  234. Text(") >").Output(manifestPath)
  235. return manifestPath
  236. }
  237. func (l *linter) getBaselineFilepath(ctx android.ModuleContext) android.OptionalPath {
  238. var lintBaseline android.OptionalPath
  239. if lintFilename := proptools.StringDefault(l.properties.Lint.Baseline_filename, "lint-baseline.xml"); lintFilename != "" {
  240. if String(l.properties.Lint.Baseline_filename) != "" {
  241. // if manually specified, we require the file to exist
  242. lintBaseline = android.OptionalPathForPath(android.PathForModuleSrc(ctx, lintFilename))
  243. } else {
  244. lintBaseline = android.ExistentPathForSource(ctx, ctx.ModuleDir(), lintFilename)
  245. }
  246. }
  247. return lintBaseline
  248. }
  249. func (l *linter) lint(ctx android.ModuleContext) {
  250. if !l.enabled() {
  251. return
  252. }
  253. if l.minSdkVersion != l.compileSdkVersion {
  254. l.extraMainlineLintErrors = append(l.extraMainlineLintErrors, updatabilityChecks...)
  255. _, filtered := android.FilterList(l.properties.Lint.Warning_checks, updatabilityChecks)
  256. if len(filtered) != 0 {
  257. ctx.PropertyErrorf("lint.warning_checks",
  258. "Can't treat %v checks as warnings if min_sdk_version is different from sdk_version.", filtered)
  259. }
  260. _, filtered = android.FilterList(l.properties.Lint.Disabled_checks, updatabilityChecks)
  261. if len(filtered) != 0 {
  262. ctx.PropertyErrorf("lint.disabled_checks",
  263. "Can't disable %v checks if min_sdk_version is different from sdk_version.", filtered)
  264. }
  265. }
  266. extraLintCheckModules := ctx.GetDirectDepsWithTag(extraLintCheckTag)
  267. for _, extraLintCheckModule := range extraLintCheckModules {
  268. if ctx.OtherModuleHasProvider(extraLintCheckModule, JavaInfoProvider) {
  269. dep := ctx.OtherModuleProvider(extraLintCheckModule, JavaInfoProvider).(JavaInfo)
  270. l.extraLintCheckJars = append(l.extraLintCheckJars, dep.ImplementationAndResourcesJars...)
  271. } else {
  272. ctx.PropertyErrorf("lint.extra_check_modules",
  273. "%s is not a java module", ctx.OtherModuleName(extraLintCheckModule))
  274. }
  275. }
  276. rule := android.NewRuleBuilder(pctx, ctx).
  277. Sbox(android.PathForModuleOut(ctx, "lint"),
  278. android.PathForModuleOut(ctx, "lint.sbox.textproto")).
  279. SandboxInputs()
  280. if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_LINT") {
  281. pool := ctx.Config().GetenvWithDefault("RBE_LINT_POOL", "java16")
  282. rule.Remoteable(android.RemoteRuleSupports{RBE: true})
  283. rule.Rewrapper(&remoteexec.REParams{
  284. Labels: map[string]string{"type": "tool", "name": "lint"},
  285. ExecStrategy: lintRBEExecStrategy(ctx),
  286. ToolchainInputs: []string{config.JavaCmd(ctx).String()},
  287. EnvironmentVariables: []string{
  288. "LANG",
  289. },
  290. Platform: map[string]string{remoteexec.PoolKey: pool},
  291. })
  292. }
  293. if l.manifest == nil {
  294. manifest := l.generateManifest(ctx, rule)
  295. l.manifest = manifest
  296. rule.Temporary(manifest)
  297. }
  298. lintPaths := l.writeLintProjectXML(ctx, rule)
  299. html := android.PathForModuleOut(ctx, "lint", "lint-report.html")
  300. text := android.PathForModuleOut(ctx, "lint", "lint-report.txt")
  301. xml := android.PathForModuleOut(ctx, "lint", "lint-report.xml")
  302. depSetsBuilder := NewLintDepSetBuilder().Direct(html, text, xml)
  303. ctx.VisitDirectDepsWithTag(staticLibTag, func(dep android.Module) {
  304. if depLint, ok := dep.(lintDepSetsIntf); ok {
  305. depSetsBuilder.Transitive(depLint.LintDepSets())
  306. }
  307. })
  308. rule.Command().Text("rm -rf").Flag(lintPaths.cacheDir.String()).Flag(lintPaths.homeDir.String())
  309. rule.Command().Text("mkdir -p").Flag(lintPaths.cacheDir.String()).Flag(lintPaths.homeDir.String())
  310. rule.Command().Text("rm -f").Output(html).Output(text).Output(xml)
  311. var annotationsZipPath, apiVersionsXMLPath android.Path
  312. if ctx.Config().AlwaysUsePrebuiltSdks() {
  313. annotationsZipPath = android.PathForSource(ctx, "prebuilts/sdk/current/public/data/annotations.zip")
  314. apiVersionsXMLPath = android.PathForSource(ctx, "prebuilts/sdk/current/public/data/api-versions.xml")
  315. } else {
  316. annotationsZipPath = copiedAnnotationsZipPath(ctx)
  317. apiVersionsXMLPath = copiedAPIVersionsXmlPath(ctx)
  318. }
  319. cmd := rule.Command()
  320. cmd.Flag(`JAVA_OPTS="-Xmx3072m --add-opens java.base/java.util=ALL-UNNAMED"`).
  321. FlagWithArg("ANDROID_SDK_HOME=", lintPaths.homeDir.String()).
  322. FlagWithInput("SDK_ANNOTATIONS=", annotationsZipPath).
  323. FlagWithInput("LINT_OPTS=-DLINT_API_DATABASE=", apiVersionsXMLPath)
  324. cmd.BuiltTool("lint").ImplicitTool(ctx.Config().HostJavaToolPath(ctx, "lint.jar")).
  325. Flag("--quiet").
  326. FlagWithInput("--project ", lintPaths.projectXML).
  327. FlagWithInput("--config ", lintPaths.configXML).
  328. FlagWithOutput("--html ", html).
  329. FlagWithOutput("--text ", text).
  330. FlagWithOutput("--xml ", xml).
  331. FlagWithArg("--compile-sdk-version ", l.compileSdkVersion).
  332. FlagWithArg("--java-language-level ", l.javaLanguageLevel).
  333. FlagWithArg("--kotlin-language-level ", l.kotlinLanguageLevel).
  334. FlagWithArg("--url ", fmt.Sprintf(".=.,%s=out", android.PathForOutput(ctx).String())).
  335. Flag("--exitcode").
  336. Flags(l.properties.Lint.Flags).
  337. Implicit(annotationsZipPath).
  338. Implicit(apiVersionsXMLPath)
  339. rule.Temporary(lintPaths.projectXML)
  340. rule.Temporary(lintPaths.configXML)
  341. if checkOnly := ctx.Config().Getenv("ANDROID_LINT_CHECK"); checkOnly != "" {
  342. cmd.FlagWithArg("--check ", checkOnly)
  343. }
  344. lintBaseline := l.getBaselineFilepath(ctx)
  345. if lintBaseline.Valid() {
  346. cmd.FlagWithInput("--baseline ", lintBaseline.Path())
  347. }
  348. cmd.Text("|| (").Text("if [ -e").Input(text).Text("]; then cat").Input(text).Text("; fi; exit 7)")
  349. rule.Command().Text("rm -rf").Flag(lintPaths.cacheDir.String()).Flag(lintPaths.homeDir.String())
  350. // The HTML output contains a date, remove it to make the output deterministic.
  351. rule.Command().Text(`sed -i.tmp -e 's|Check performed at .*\(</nav>\)|\1|'`).Output(html)
  352. rule.Build("lint", "lint")
  353. l.outputs = lintOutputs{
  354. html: html,
  355. text: text,
  356. xml: xml,
  357. depSets: depSetsBuilder.Build(),
  358. }
  359. if l.buildModuleReportZip {
  360. l.reports = BuildModuleLintReportZips(ctx, l.LintDepSets())
  361. }
  362. }
  363. func BuildModuleLintReportZips(ctx android.ModuleContext, depSets LintDepSets) android.Paths {
  364. htmlList := depSets.HTML.ToSortedList()
  365. textList := depSets.Text.ToSortedList()
  366. xmlList := depSets.XML.ToSortedList()
  367. if len(htmlList) == 0 && len(textList) == 0 && len(xmlList) == 0 {
  368. return nil
  369. }
  370. htmlZip := android.PathForModuleOut(ctx, "lint-report-html.zip")
  371. lintZip(ctx, htmlList, htmlZip)
  372. textZip := android.PathForModuleOut(ctx, "lint-report-text.zip")
  373. lintZip(ctx, textList, textZip)
  374. xmlZip := android.PathForModuleOut(ctx, "lint-report-xml.zip")
  375. lintZip(ctx, xmlList, xmlZip)
  376. return android.Paths{htmlZip, textZip, xmlZip}
  377. }
  378. type lintSingleton struct {
  379. htmlZip android.WritablePath
  380. textZip android.WritablePath
  381. xmlZip android.WritablePath
  382. }
  383. func (l *lintSingleton) GenerateBuildActions(ctx android.SingletonContext) {
  384. l.generateLintReportZips(ctx)
  385. l.copyLintDependencies(ctx)
  386. }
  387. func (l *lintSingleton) copyLintDependencies(ctx android.SingletonContext) {
  388. if ctx.Config().AlwaysUsePrebuiltSdks() {
  389. return
  390. }
  391. var frameworkDocStubs android.Module
  392. ctx.VisitAllModules(func(m android.Module) {
  393. if ctx.ModuleName(m) == "framework-doc-stubs" {
  394. if frameworkDocStubs == nil {
  395. frameworkDocStubs = m
  396. } else {
  397. ctx.Errorf("lint: multiple framework-doc-stubs modules found: %s and %s",
  398. ctx.ModuleSubDir(m), ctx.ModuleSubDir(frameworkDocStubs))
  399. }
  400. }
  401. })
  402. if frameworkDocStubs == nil {
  403. if !ctx.Config().AllowMissingDependencies() {
  404. ctx.Errorf("lint: missing framework-doc-stubs")
  405. }
  406. return
  407. }
  408. ctx.Build(pctx, android.BuildParams{
  409. Rule: android.CpIfChanged,
  410. Input: android.OutputFileForModule(ctx, frameworkDocStubs, ".annotations.zip"),
  411. Output: copiedAnnotationsZipPath(ctx),
  412. })
  413. ctx.Build(pctx, android.BuildParams{
  414. Rule: android.CpIfChanged,
  415. Input: android.OutputFileForModule(ctx, frameworkDocStubs, ".api_versions.xml"),
  416. Output: copiedAPIVersionsXmlPath(ctx),
  417. })
  418. }
  419. func copiedAnnotationsZipPath(ctx android.PathContext) android.WritablePath {
  420. return android.PathForOutput(ctx, "lint", "annotations.zip")
  421. }
  422. func copiedAPIVersionsXmlPath(ctx android.PathContext) android.WritablePath {
  423. return android.PathForOutput(ctx, "lint", "api_versions.xml")
  424. }
  425. func (l *lintSingleton) generateLintReportZips(ctx android.SingletonContext) {
  426. if ctx.Config().UnbundledBuild() {
  427. return
  428. }
  429. var outputs []*lintOutputs
  430. var dirs []string
  431. ctx.VisitAllModules(func(m android.Module) {
  432. if ctx.Config().KatiEnabled() && !m.ExportedToMake() {
  433. return
  434. }
  435. if apex, ok := m.(android.ApexModule); ok && apex.NotAvailableForPlatform() {
  436. apexInfo := ctx.ModuleProvider(m, android.ApexInfoProvider).(android.ApexInfo)
  437. if apexInfo.IsForPlatform() {
  438. // There are stray platform variants of modules in apexes that are not available for
  439. // the platform, and they sometimes can't be built. Don't depend on them.
  440. return
  441. }
  442. }
  443. if l, ok := m.(lintOutputsIntf); ok {
  444. outputs = append(outputs, l.lintOutputs())
  445. }
  446. })
  447. dirs = android.SortedUniqueStrings(dirs)
  448. zip := func(outputPath android.WritablePath, get func(*lintOutputs) android.Path) {
  449. var paths android.Paths
  450. for _, output := range outputs {
  451. if p := get(output); p != nil {
  452. paths = append(paths, p)
  453. }
  454. }
  455. lintZip(ctx, paths, outputPath)
  456. }
  457. l.htmlZip = android.PathForOutput(ctx, "lint-report-html.zip")
  458. zip(l.htmlZip, func(l *lintOutputs) android.Path { return l.html })
  459. l.textZip = android.PathForOutput(ctx, "lint-report-text.zip")
  460. zip(l.textZip, func(l *lintOutputs) android.Path { return l.text })
  461. l.xmlZip = android.PathForOutput(ctx, "lint-report-xml.zip")
  462. zip(l.xmlZip, func(l *lintOutputs) android.Path { return l.xml })
  463. ctx.Phony("lint-check", l.htmlZip, l.textZip, l.xmlZip)
  464. }
  465. func (l *lintSingleton) MakeVars(ctx android.MakeVarsContext) {
  466. if !ctx.Config().UnbundledBuild() {
  467. ctx.DistForGoal("lint-check", l.htmlZip, l.textZip, l.xmlZip)
  468. }
  469. }
  470. var _ android.SingletonMakeVarsProvider = (*lintSingleton)(nil)
  471. func init() {
  472. android.RegisterSingletonType("lint",
  473. func() android.Singleton { return &lintSingleton{} })
  474. }
  475. func lintZip(ctx android.BuilderContext, paths android.Paths, outputPath android.WritablePath) {
  476. paths = android.SortedUniquePaths(android.CopyOfPaths(paths))
  477. sort.Slice(paths, func(i, j int) bool {
  478. return paths[i].String() < paths[j].String()
  479. })
  480. rule := android.NewRuleBuilder(pctx, ctx)
  481. rule.Command().BuiltTool("soong_zip").
  482. FlagWithOutput("-o ", outputPath).
  483. FlagWithArg("-C ", android.PathForIntermediates(ctx).String()).
  484. FlagWithRspFileInputList("-r ", outputPath.ReplaceExtension(ctx, "rsp"), paths)
  485. rule.Build(outputPath.Base(), outputPath.Base())
  486. }