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
This commit is contained in:
parent
9e44e21e91
commit
c0efd1db13
|
@ -107,6 +107,25 @@ func (a *AndroidMkEntries) SetPath(name string, path Path) {
|
||||||
a.EntryMap[name] = []string{path.String()}
|
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) {
|
func (a *AndroidMkEntries) SetBoolIfTrue(name string, flag bool) {
|
||||||
if flag {
|
if flag {
|
||||||
if _, ok := a.EntryMap[name]; !ok {
|
if _, ok := a.EntryMap[name]; !ok {
|
||||||
|
|
|
@ -484,6 +484,10 @@ func (p Paths) Strings() []string {
|
||||||
return ret
|
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
|
// 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.
|
// modifies the Paths slice contents in place, and returns a subslice of the original slice.
|
||||||
func FirstUniquePaths(list Paths) Paths {
|
func FirstUniquePaths(list Paths) Paths {
|
||||||
|
@ -494,7 +498,8 @@ func FirstUniquePaths(list Paths) Paths {
|
||||||
return firstUniquePathsList(list)
|
return firstUniquePathsList(list)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SortedUniquePaths returns what its name says
|
// SortedUniquePaths returns all unique elements of a Paths in sorted order. It modifies the
|
||||||
|
// Paths slice contents in place, and returns a subslice of the original slice.
|
||||||
func SortedUniquePaths(list Paths) Paths {
|
func SortedUniquePaths(list Paths) Paths {
|
||||||
unique := FirstUniquePaths(list)
|
unique := FirstUniquePaths(list)
|
||||||
sort.Slice(unique, func(i, j int) bool {
|
sort.Slice(unique, func(i, j int) bool {
|
||||||
|
|
|
@ -131,6 +131,10 @@ func (library *Library) AndroidMkEntries() []android.AndroidMkEntries {
|
||||||
entries.SetPath("LOCAL_SOONG_PROGUARD_DICT", library.proguardDictionary)
|
entries.SetPath("LOCAL_SOONG_PROGUARD_DICT", library.proguardDictionary)
|
||||||
}
|
}
|
||||||
entries.SetString("LOCAL_MODULE_STEM", library.Stem())
|
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()
|
install := app.onDeviceDir + "/" + extra.Base()
|
||||||
entries.AddStrings("LOCAL_SOONG_BUILT_INSTALLED", extra.String()+":"+install)
|
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{
|
ExtraFooters: []android.AndroidMkExtraFootersFunc{
|
||||||
|
|
|
@ -752,6 +752,7 @@ func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) {
|
||||||
a.linter.mergedManifest = a.aapt.mergedManifestFile
|
a.linter.mergedManifest = a.aapt.mergedManifestFile
|
||||||
a.linter.manifest = a.aapt.manifestPath
|
a.linter.manifest = a.aapt.manifestPath
|
||||||
a.linter.resources = a.aapt.resourceFiles
|
a.linter.resources = a.aapt.resourceFiles
|
||||||
|
a.linter.buildModuleReportZip = ctx.Config().UnbundledBuildApps()
|
||||||
|
|
||||||
dexJarFile := a.dexBuildActions(ctx)
|
dexJarFile := a.dexBuildActions(ctx)
|
||||||
|
|
||||||
|
|
107
java/lint.go
107
java/lint.go
|
@ -67,12 +67,32 @@ type linter struct {
|
||||||
kotlinLanguageLevel string
|
kotlinLanguageLevel string
|
||||||
outputs lintOutputs
|
outputs lintOutputs
|
||||||
properties LintProperties
|
properties LintProperties
|
||||||
|
|
||||||
|
buildModuleReportZip bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type lintOutputs struct {
|
type lintOutputs struct {
|
||||||
html android.ModuleOutPath
|
html android.ModuleOutPath
|
||||||
text android.ModuleOutPath
|
text android.ModuleOutPath
|
||||||
xml 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 {
|
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)
|
projectXML, lintXML, cacheDir, homeDir, deps := l.writeLintProjectXML(ctx, rule)
|
||||||
|
|
||||||
l.outputs.html = android.PathForModuleOut(ctx, "lint-report.html")
|
html := android.PathForModuleOut(ctx, "lint-report.html")
|
||||||
l.outputs.text = android.PathForModuleOut(ctx, "lint-report.txt")
|
text := android.PathForModuleOut(ctx, "lint-report.txt")
|
||||||
l.outputs.xml = android.PathForModuleOut(ctx, "lint-report.xml")
|
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("rm -rf").Flag(cacheDir.String()).Flag(homeDir.String())
|
||||||
rule.Command().Text("mkdir -p").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").
|
Flag("--quiet").
|
||||||
FlagWithInput("--project ", projectXML).
|
FlagWithInput("--project ", projectXML).
|
||||||
FlagWithInput("--config ", lintXML).
|
FlagWithInput("--config ", lintXML).
|
||||||
FlagWithOutput("--html ", l.outputs.html).
|
FlagWithOutput("--html ", html).
|
||||||
FlagWithOutput("--text ", l.outputs.text).
|
FlagWithOutput("--text ", text).
|
||||||
FlagWithOutput("--xml ", l.outputs.xml).
|
FlagWithOutput("--xml ", xml).
|
||||||
FlagWithArg("--compile-sdk-version ", l.compileSdkVersion).
|
FlagWithArg("--compile-sdk-version ", l.compileSdkVersion).
|
||||||
FlagWithArg("--java-language-level ", l.javaLanguageLevel).
|
FlagWithArg("--java-language-level ", l.javaLanguageLevel).
|
||||||
FlagWithArg("--kotlin-language-level ", l.kotlinLanguageLevel).
|
FlagWithArg("--kotlin-language-level ", l.kotlinLanguageLevel).
|
||||||
|
@ -250,23 +283,37 @@ func (l *linter) lint(ctx android.ModuleContext) {
|
||||||
Flag("--exitcode").
|
Flag("--exitcode").
|
||||||
Flags(l.properties.Lint.Flags).
|
Flags(l.properties.Lint.Flags).
|
||||||
Implicits(deps).
|
Implicits(deps).
|
||||||
Text("|| (").Text("cat").Input(l.outputs.text).Text("; exit 7)").
|
Text("|| (").Text("cat").Input(text).Text("; exit 7)").
|
||||||
Text(")")
|
Text(")")
|
||||||
|
|
||||||
rule.Command().Text("rm -rf").Flag(cacheDir.String()).Flag(homeDir.String())
|
rule.Command().Text("rm -rf").Flag(cacheDir.String()).Flag(homeDir.String())
|
||||||
|
|
||||||
rule.Build(pctx, ctx, "lint", "lint")
|
rule.Build(pctx, ctx, "lint", "lint")
|
||||||
}
|
|
||||||
|
|
||||||
func (l *linter) lintOutputs() *lintOutputs {
|
l.outputs = lintOutputs{
|
||||||
return &l.outputs
|
html: html,
|
||||||
}
|
text: text,
|
||||||
|
xml: xml,
|
||||||
|
|
||||||
type lintOutputIntf interface {
|
transitiveHTML: htmlDeps.Build(),
|
||||||
lintOutputs() *lintOutputs
|
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 {
|
type lintSingleton struct {
|
||||||
htmlZip android.WritablePath
|
htmlZip android.WritablePath
|
||||||
|
@ -356,18 +403,7 @@ func (l *lintSingleton) generateLintReportZips(ctx android.SingletonContext) {
|
||||||
paths = append(paths, get(output))
|
paths = append(paths, get(output))
|
||||||
}
|
}
|
||||||
|
|
||||||
sort.Slice(paths, func(i, j int) bool {
|
lintZip(ctx, paths, outputPath)
|
||||||
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())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
l.htmlZip = android.PathForOutput(ctx, "lint-report-html.zip")
|
l.htmlZip = android.PathForOutput(ctx, "lint-report-html.zip")
|
||||||
|
@ -394,3 +430,20 @@ func init() {
|
||||||
android.RegisterSingletonType("lint",
|
android.RegisterSingletonType("lint",
|
||||||
func() android.Singleton { return &lintSingleton{} })
|
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())
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue