Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1d11c871 authored by Colin Cross's avatar Colin Cross
Browse files

Build a zip of transitive lint reports for apps

Add a rule to build a zip containing the lint reports from transitive
dependencies for apps, and pass it to Make.

Bug: 153485543
Test: m TARGET_BUILD_APPS=Gallery2 lint-check
Change-Id: I523c09016251377ff89d76084769be7401b95425
Merged-In: I523c09016251377ff89d76084769be7401b95425
(cherry picked from commit c0efd1db)
parent 70f59094
Loading
Loading
Loading
Loading
+19 −0
Original line number Diff line number Diff line
@@ -107,6 +107,25 @@ func (a *AndroidMkEntries) SetPath(name string, path Path) {
	a.EntryMap[name] = []string{path.String()}
}

func (a *AndroidMkEntries) SetOptionalPath(name string, path OptionalPath) {
	if path.Valid() {
		a.SetPath(name, path.Path())
	}
}

func (a *AndroidMkEntries) AddPath(name string, path Path) {
	if _, ok := a.EntryMap[name]; !ok {
		a.entryOrder = append(a.entryOrder, name)
	}
	a.EntryMap[name] = append(a.EntryMap[name], path.String())
}

func (a *AndroidMkEntries) AddOptionalPath(name string, path OptionalPath) {
	if path.Valid() {
		a.AddPath(name, path.Path())
	}
}

func (a *AndroidMkEntries) SetBoolIfTrue(name string, flag bool) {
	if flag {
		if _, ok := a.EntryMap[name]; !ok {
+4 −0
Original line number Diff line number Diff line
@@ -466,6 +466,10 @@ func (p Paths) Strings() []string {
	return ret
}

func CopyOfPaths(paths Paths) Paths {
	return append(Paths(nil), paths...)
}

// FirstUniquePaths returns all unique elements of a Paths, keeping the first copy of each.  It
// modifies the Paths slice contents in place, and returns a subslice of the original slice.
func FirstUniquePaths(list Paths) Paths {
+8 −0
Original line number Diff line number Diff line
@@ -131,6 +131,10 @@ func (library *Library) AndroidMkEntries() []android.AndroidMkEntries {
						entries.SetPath("LOCAL_SOONG_PROGUARD_DICT", library.proguardDictionary)
					}
					entries.SetString("LOCAL_MODULE_STEM", library.Stem())

					entries.AddOptionalPath("LOCAL_SOONG_LINT_REPORTS", library.linter.outputs.transitiveHTMLZip)
					entries.AddOptionalPath("LOCAL_SOONG_LINT_REPORTS", library.linter.outputs.transitiveTextZip)
					entries.AddOptionalPath("LOCAL_SOONG_LINT_REPORTS", library.linter.outputs.transitiveXMLZip)
				},
			},
		}
@@ -383,6 +387,10 @@ func (app *AndroidApp) AndroidMkEntries() []android.AndroidMkEntries {
					install := app.onDeviceDir + "/" + extra.Base()
					entries.AddStrings("LOCAL_SOONG_BUILT_INSTALLED", extra.String()+":"+install)
				}

				entries.AddOptionalPath("LOCAL_SOONG_LINT_REPORTS", app.linter.outputs.transitiveHTMLZip)
				entries.AddOptionalPath("LOCAL_SOONG_LINT_REPORTS", app.linter.outputs.transitiveTextZip)
				entries.AddOptionalPath("LOCAL_SOONG_LINT_REPORTS", app.linter.outputs.transitiveXMLZip)
			},
		},
		ExtraFooters: []android.AndroidMkExtraFootersFunc{
+1 −0
Original line number Diff line number Diff line
@@ -749,6 +749,7 @@ func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) {
	a.linter.mergedManifest = a.aapt.mergedManifestFile
	a.linter.manifest = a.aapt.manifestPath
	a.linter.resources = a.aapt.resourceFiles
	a.linter.buildModuleReportZip = ctx.Config().UnbundledBuild()

	dexJarFile := a.dexBuildActions(ctx)

+80 −27
Original line number Diff line number Diff line
@@ -67,12 +67,32 @@ type linter struct {
	kotlinLanguageLevel string
	outputs             lintOutputs
	properties          LintProperties

	buildModuleReportZip bool
}

type lintOutputs struct {
	html android.ModuleOutPath
	text android.ModuleOutPath
	xml  android.ModuleOutPath

	transitiveHTML *android.DepSet
	transitiveText *android.DepSet
	transitiveXML  *android.DepSet

	transitiveHTMLZip android.OptionalPath
	transitiveTextZip android.OptionalPath
	transitiveXMLZip  android.OptionalPath
}

type lintOutputIntf interface {
	lintOutputs() *lintOutputs
}

var _ lintOutputIntf = (*linter)(nil)

func (l *linter) lintOutputs() *lintOutputs {
	return &l.outputs
}

func (l *linter) enabled() bool {
@@ -213,9 +233,22 @@ func (l *linter) lint(ctx android.ModuleContext) {

	projectXML, lintXML, cacheDir, homeDir, deps := l.writeLintProjectXML(ctx, rule)

	l.outputs.html = android.PathForModuleOut(ctx, "lint-report.html")
	l.outputs.text = android.PathForModuleOut(ctx, "lint-report.txt")
	l.outputs.xml = android.PathForModuleOut(ctx, "lint-report.xml")
	html := android.PathForModuleOut(ctx, "lint-report.html")
	text := android.PathForModuleOut(ctx, "lint-report.txt")
	xml := android.PathForModuleOut(ctx, "lint-report.xml")

	htmlDeps := android.NewDepSetBuilder(android.POSTORDER).Direct(html)
	textDeps := android.NewDepSetBuilder(android.POSTORDER).Direct(text)
	xmlDeps := android.NewDepSetBuilder(android.POSTORDER).Direct(xml)

	ctx.VisitDirectDepsWithTag(staticLibTag, func(dep android.Module) {
		if depLint, ok := dep.(lintOutputIntf); ok {
			depLintOutputs := depLint.lintOutputs()
			htmlDeps.Transitive(depLintOutputs.transitiveHTML)
			textDeps.Transitive(depLintOutputs.transitiveText)
			xmlDeps.Transitive(depLintOutputs.transitiveXML)
		}
	})

	rule.Command().Text("rm -rf").Flag(cacheDir.String()).Flag(homeDir.String())
	rule.Command().Text("mkdir -p").Flag(cacheDir.String()).Flag(homeDir.String())
@@ -240,9 +273,9 @@ func (l *linter) lint(ctx android.ModuleContext) {
		Flag("--quiet").
		FlagWithInput("--project ", projectXML).
		FlagWithInput("--config ", lintXML).
		FlagWithOutput("--html ", l.outputs.html).
		FlagWithOutput("--text ", l.outputs.text).
		FlagWithOutput("--xml ", l.outputs.xml).
		FlagWithOutput("--html ", html).
		FlagWithOutput("--text ", text).
		FlagWithOutput("--xml ", xml).
		FlagWithArg("--compile-sdk-version ", l.compileSdkVersion).
		FlagWithArg("--java-language-level ", l.javaLanguageLevel).
		FlagWithArg("--kotlin-language-level ", l.kotlinLanguageLevel).
@@ -250,23 +283,37 @@ func (l *linter) lint(ctx android.ModuleContext) {
		Flag("--exitcode").
		Flags(l.properties.Lint.Flags).
		Implicits(deps).
		Text("|| (").Text("cat").Input(l.outputs.text).Text("; exit 7)").
		Text("|| (").Text("cat").Input(text).Text("; exit 7)").
		Text(")")

	rule.Command().Text("rm -rf").Flag(cacheDir.String()).Flag(homeDir.String())

	rule.Build(pctx, ctx, "lint", "lint")
}

func (l *linter) lintOutputs() *lintOutputs {
	return &l.outputs
}
	l.outputs = lintOutputs{
		html: html,
		text: text,
		xml:  xml,

type lintOutputIntf interface {
	lintOutputs() *lintOutputs
		transitiveHTML: htmlDeps.Build(),
		transitiveText: textDeps.Build(),
		transitiveXML:  xmlDeps.Build(),
	}

var _ lintOutputIntf = (*linter)(nil)
	if l.buildModuleReportZip {
		htmlZip := android.PathForModuleOut(ctx, "lint-report-html.zip")
		l.outputs.transitiveHTMLZip = android.OptionalPathForPath(htmlZip)
		lintZip(ctx, l.outputs.transitiveHTML.ToSortedList(), htmlZip)

		textZip := android.PathForModuleOut(ctx, "lint-report-text.zip")
		l.outputs.transitiveTextZip = android.OptionalPathForPath(textZip)
		lintZip(ctx, l.outputs.transitiveText.ToSortedList(), textZip)

		xmlZip := android.PathForModuleOut(ctx, "lint-report-xml.zip")
		l.outputs.transitiveXMLZip = android.OptionalPathForPath(xmlZip)
		lintZip(ctx, l.outputs.transitiveXML.ToSortedList(), xmlZip)
	}
}

type lintSingleton struct {
	htmlZip android.WritablePath
@@ -356,18 +403,7 @@ func (l *lintSingleton) generateLintReportZips(ctx android.SingletonContext) {
			paths = append(paths, get(output))
		}

		sort.Slice(paths, func(i, j int) bool {
			return paths[i].String() < paths[j].String()
		})

		rule := android.NewRuleBuilder()

		rule.Command().BuiltTool(ctx, "soong_zip").
			FlagWithOutput("-o ", outputPath).
			FlagWithArg("-C ", android.PathForIntermediates(ctx).String()).
			FlagWithRspFileInputList("-l ", paths)

		rule.Build(pctx, ctx, outputPath.Base(), outputPath.Base())
		lintZip(ctx, paths, outputPath)
	}

	l.htmlZip = android.PathForOutput(ctx, "lint-report-html.zip")
@@ -394,3 +430,20 @@ func init() {
	android.RegisterSingletonType("lint",
		func() android.Singleton { return &lintSingleton{} })
}

func lintZip(ctx android.BuilderContext, paths android.Paths, outputPath android.WritablePath) {
	paths = android.SortedUniquePaths(android.CopyOfPaths(paths))

	sort.Slice(paths, func(i, j int) bool {
		return paths[i].String() < paths[j].String()
	})

	rule := android.NewRuleBuilder()

	rule.Command().BuiltTool(ctx, "soong_zip").
		FlagWithOutput("-o ", outputPath).
		FlagWithArg("-C ", android.PathForIntermediates(ctx).String()).
		FlagWithRspFileInputList("-l ", paths)

	rule.Build(pctx, ctx, outputPath.Base(), outputPath.Base())
}