diff --git a/android/androidmk.go b/android/androidmk.go index 94b4b8175..7e8614031 100644 --- a/android/androidmk.go +++ b/android/androidmk.go @@ -126,6 +126,26 @@ func (a *AndroidMkEntries) AddOptionalPath(name string, path OptionalPath) { } } +func (a *AndroidMkEntries) SetPaths(name string, paths Paths) { + if _, ok := a.EntryMap[name]; !ok { + a.entryOrder = append(a.entryOrder, name) + } + a.EntryMap[name] = paths.Strings() +} + +func (a *AndroidMkEntries) SetOptionalPaths(name string, paths Paths) { + if len(paths) > 0 { + a.SetPaths(name, paths) + } +} + +func (a *AndroidMkEntries) AddPaths(name string, paths Paths) { + if _, ok := a.EntryMap[name]; !ok { + a.entryOrder = append(a.entryOrder, name) + } + a.EntryMap[name] = append(a.EntryMap[name], paths.Strings()...) +} + func (a *AndroidMkEntries) SetBoolIfTrue(name string, flag bool) { if flag { if _, ok := a.EntryMap[name]; !ok { diff --git a/apex/androidmk.go b/apex/androidmk.go index 10cc4b6c2..e739e2ba5 100644 --- a/apex/androidmk.go +++ b/apex/androidmk.go @@ -353,6 +353,10 @@ func (a *apexBundle) androidMkForType() android.AndroidMkData { if apexType == imageApex { fmt.Fprintln(w, "ALL_MODULES.$(my_register_name).BUNDLE :=", a.bundleModuleFile.String()) } + if len(a.lintReports) > 0 { + fmt.Fprintln(w, "ALL_MODULES.$(my_register_name).LINT_REPORTS :=", + strings.Join(a.lintReports.Strings(), " ")) + } if a.installedFilesFile != nil { goal := "checkbuild" diff --git a/apex/apex.go b/apex/apex.go index d0c4e6ec4..7f695b4ae 100644 --- a/apex/apex.go +++ b/apex/apex.go @@ -1154,6 +1154,7 @@ type apexFile struct { hostRequiredModuleNames []string jacocoReportClassesFile android.Path // only for javalibs and apps + lintDepSets java.LintDepSets // only for javalibs and apps certificate java.Certificate // only for apps overriddenPackageName string // only for apps @@ -1278,6 +1279,9 @@ type apexBundle struct { // Struct holding the merged notice file paths in different formats mergedNotices android.NoticeOutputs + + // Optional list of lint report zip files for apexes that contain java or app modules + lintReports android.Paths } func addDependenciesForNativeModules(ctx android.BottomUpMutatorContext, @@ -1666,9 +1670,16 @@ func apexFileForShBinary(ctx android.BaseModuleContext, sh *sh.ShBinary) apexFil type javaDependency interface { DexJarBuildPath() android.Path JacocoReportClassesFile() android.Path + LintDepSets() java.LintDepSets + Stem() string } +var _ javaDependency = (*java.Library)(nil) +var _ javaDependency = (*java.SdkLibrary)(nil) +var _ javaDependency = (*java.DexImport)(nil) +var _ javaDependency = (*java.SdkLibraryImport)(nil) + func apexFileForJavaLibrary(ctx android.BaseModuleContext, lib javaDependency, module android.Module) apexFile { dirInApex := "javalib" fileToCopy := lib.DexJarBuildPath() @@ -1676,6 +1687,7 @@ func apexFileForJavaLibrary(ctx android.BaseModuleContext, lib javaDependency, m name := strings.TrimPrefix(module.Name(), "prebuilt_") af := newApexFile(ctx, fileToCopy, name, dirInApex, javaSharedLib, module) af.jacocoReportClassesFile = lib.JacocoReportClassesFile() + af.lintDepSets = lib.LintDepSets() af.stem = lib.Stem() + ".jar" return af } @@ -2275,6 +2287,8 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) { a.compatSymlinks = makeCompatSymlinks(a.BaseModuleName(), ctx) a.buildApexDependencyInfo(ctx) + + a.buildLintReports(ctx) } // Enforce that Java deps of the apex are using stable SDKs to compile diff --git a/apex/builder.go b/apex/builder.go index a70c7672c..0a1ec3eb3 100644 --- a/apex/builder.go +++ b/apex/builder.go @@ -815,3 +815,12 @@ func (a *apexBundle) buildApexDependencyInfo(ctx android.ModuleContext) { }, }) } + +func (a *apexBundle) buildLintReports(ctx android.ModuleContext) { + depSetsBuilder := java.NewLintDepSetBuilder() + for _, fi := range a.filesInfo { + depSetsBuilder.Transitive(fi.lintDepSets) + } + + a.lintReports = java.BuildModuleLintReportZips(ctx, depSetsBuilder.Build()) +} diff --git a/java/androidmk.go b/java/androidmk.go index 03994bfd6..25dd32931 100644 --- a/java/androidmk.go +++ b/java/androidmk.go @@ -132,9 +132,7 @@ func (library *Library) AndroidMkEntries() []android.AndroidMkEntries { } 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) + entries.SetOptionalPaths("LOCAL_SOONG_LINT_REPORTS", library.linter.reports) }, }, } @@ -394,9 +392,7 @@ func (app *AndroidApp) AndroidMkEntries() []android.AndroidMkEntries { 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) + entries.SetOptionalPaths("LOCAL_SOONG_LINT_REPORTS", app.linter.reports) }, }, ExtraFooters: []android.AndroidMkExtraFootersFunc{ diff --git a/java/java.go b/java/java.go index 367b09cbb..ef9613df0 100644 --- a/java/java.go +++ b/java/java.go @@ -1707,6 +1707,9 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) { j.linter.compileSdkVersion = lintSDKVersionString(j.sdkVersion()) j.linter.javaLanguageLevel = flags.javaVersion.String() j.linter.kotlinLanguageLevel = "1.3" + if j.ApexName() != "" && ctx.Config().UnbundledBuildApps() { + j.linter.buildModuleReportZip = true + } j.linter.lint(ctx) } @@ -2789,6 +2792,10 @@ func (a *DexImport) JacocoReportClassesFile() android.Path { return nil } +func (a *DexImport) LintDepSets() LintDepSets { + return LintDepSets{} +} + func (j *DexImport) IsInstallable() bool { return true } diff --git a/java/lint.go b/java/lint.go index 5d2c4f614..639106793 100644 --- a/java/lint.go +++ b/java/lint.go @@ -69,28 +69,78 @@ type linter struct { outputs lintOutputs properties LintProperties + reports android.Paths + buildModuleReportZip bool } type lintOutputs struct { - html android.ModuleOutPath - text android.ModuleOutPath - xml android.ModuleOutPath + html android.Path + text android.Path + xml android.Path - transitiveHTML *android.DepSet - transitiveText *android.DepSet - transitiveXML *android.DepSet - - transitiveHTMLZip android.OptionalPath - transitiveTextZip android.OptionalPath - transitiveXMLZip android.OptionalPath + depSets LintDepSets } -type lintOutputIntf interface { +type lintOutputsIntf interface { lintOutputs() *lintOutputs } -var _ lintOutputIntf = (*linter)(nil) +type lintDepSetsIntf interface { + LintDepSets() LintDepSets +} + +type LintDepSets struct { + HTML, Text, XML *android.DepSet +} + +type LintDepSetsBuilder struct { + HTML, Text, XML *android.DepSetBuilder +} + +func NewLintDepSetBuilder() LintDepSetsBuilder { + return LintDepSetsBuilder{ + HTML: android.NewDepSetBuilder(android.POSTORDER), + Text: android.NewDepSetBuilder(android.POSTORDER), + XML: android.NewDepSetBuilder(android.POSTORDER), + } +} + +func (l LintDepSetsBuilder) Direct(html, text, xml android.Path) LintDepSetsBuilder { + l.HTML.Direct(html) + l.Text.Direct(text) + l.XML.Direct(xml) + return l +} + +func (l LintDepSetsBuilder) Transitive(depSets LintDepSets) LintDepSetsBuilder { + if depSets.HTML != nil { + l.HTML.Transitive(depSets.HTML) + } + if depSets.Text != nil { + l.Text.Transitive(depSets.Text) + } + if depSets.XML != nil { + l.XML.Transitive(depSets.XML) + } + return l +} + +func (l LintDepSetsBuilder) Build() LintDepSets { + return LintDepSets{ + HTML: l.HTML.Build(), + Text: l.Text.Build(), + XML: l.XML.Build(), + } +} + +func (l *linter) LintDepSets() LintDepSets { + return l.outputs.depSets +} + +var _ lintDepSetsIntf = (*linter)(nil) + +var _ lintOutputsIntf = (*linter)(nil) func (l *linter) lintOutputs() *lintOutputs { return &l.outputs @@ -247,16 +297,11 @@ func (l *linter) lint(ctx android.ModuleContext) { 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) + depSetsBuilder := NewLintDepSetBuilder().Direct(html, text, 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) + if depLint, ok := dep.(lintDepSetsIntf); ok { + depSetsBuilder.Transitive(depLint.LintDepSets()) } }) @@ -309,26 +354,35 @@ func (l *linter) lint(ctx android.ModuleContext) { text: text, xml: xml, - transitiveHTML: htmlDeps.Build(), - transitiveText: textDeps.Build(), - transitiveXML: xmlDeps.Build(), + depSets: depSetsBuilder.Build(), } 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) + l.reports = BuildModuleLintReportZips(ctx, l.LintDepSets()) } } +func BuildModuleLintReportZips(ctx android.ModuleContext, depSets LintDepSets) android.Paths { + htmlList := depSets.HTML.ToSortedList() + textList := depSets.Text.ToSortedList() + xmlList := depSets.XML.ToSortedList() + + if len(htmlList) == 0 && len(textList) == 0 && len(xmlList) == 0 { + return nil + } + + htmlZip := android.PathForModuleOut(ctx, "lint-report-html.zip") + lintZip(ctx, htmlList, htmlZip) + + textZip := android.PathForModuleOut(ctx, "lint-report-text.zip") + lintZip(ctx, textList, textZip) + + xmlZip := android.PathForModuleOut(ctx, "lint-report-xml.zip") + lintZip(ctx, xmlList, xmlZip) + + return android.Paths{htmlZip, textZip, xmlZip} +} + type lintSingleton struct { htmlZip android.WritablePath textZip android.WritablePath @@ -403,7 +457,7 @@ func (l *lintSingleton) generateLintReportZips(ctx android.SingletonContext) { return } - if l, ok := m.(lintOutputIntf); ok { + if l, ok := m.(lintOutputsIntf); ok { outputs = append(outputs, l.lintOutputs()) } }) @@ -414,7 +468,9 @@ func (l *lintSingleton) generateLintReportZips(ctx android.SingletonContext) { var paths android.Paths for _, output := range outputs { - paths = append(paths, get(output)) + if p := get(output); p != nil { + paths = append(paths, p) + } } lintZip(ctx, paths, outputPath) diff --git a/java/sdk_library.go b/java/sdk_library.go index e3ba2c76b..8a8d0c959 100644 --- a/java/sdk_library.go +++ b/java/sdk_library.go @@ -1995,6 +1995,15 @@ func (module *SdkLibraryImport) JacocoReportClassesFile() android.Path { } } +// to satisfy apex.javaDependency interface +func (module *SdkLibraryImport) LintDepSets() LintDepSets { + if module.implLibraryModule == nil { + return LintDepSets{} + } else { + return module.implLibraryModule.LintDepSets() + } +} + // to satisfy apex.javaDependency interface func (module *SdkLibraryImport) Stem() string { return module.BaseModuleName()