1*333d2b36SAndroid Build Coastguard Worker// Copyright 2020 Google Inc. All rights reserved. 2*333d2b36SAndroid Build Coastguard Worker// 3*333d2b36SAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License"); 4*333d2b36SAndroid Build Coastguard Worker// you may not use this file except in compliance with the License. 5*333d2b36SAndroid Build Coastguard Worker// You may obtain a copy of the License at 6*333d2b36SAndroid Build Coastguard Worker// 7*333d2b36SAndroid Build Coastguard Worker// http://www.apache.org/licenses/LICENSE-2.0 8*333d2b36SAndroid Build Coastguard Worker// 9*333d2b36SAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software 10*333d2b36SAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS, 11*333d2b36SAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*333d2b36SAndroid Build Coastguard Worker// See the License for the specific language governing permissions and 13*333d2b36SAndroid Build Coastguard Worker// limitations under the License. 14*333d2b36SAndroid Build Coastguard Worker 15*333d2b36SAndroid Build Coastguard Workerpackage java 16*333d2b36SAndroid Build Coastguard Worker 17*333d2b36SAndroid Build Coastguard Workerimport ( 18*333d2b36SAndroid Build Coastguard Worker "fmt" 19*333d2b36SAndroid Build Coastguard Worker "sort" 20*333d2b36SAndroid Build Coastguard Worker "strings" 21*333d2b36SAndroid Build Coastguard Worker 22*333d2b36SAndroid Build Coastguard Worker "github.com/google/blueprint" 23*333d2b36SAndroid Build Coastguard Worker "github.com/google/blueprint/depset" 24*333d2b36SAndroid Build Coastguard Worker "github.com/google/blueprint/proptools" 25*333d2b36SAndroid Build Coastguard Worker 26*333d2b36SAndroid Build Coastguard Worker "android/soong/android" 27*333d2b36SAndroid Build Coastguard Worker "android/soong/java/config" 28*333d2b36SAndroid Build Coastguard Worker "android/soong/remoteexec" 29*333d2b36SAndroid Build Coastguard Worker) 30*333d2b36SAndroid Build Coastguard Worker 31*333d2b36SAndroid Build Coastguard Worker// lint checks automatically enforced for modules that have different min_sdk_version than 32*333d2b36SAndroid Build Coastguard Worker// sdk_version 33*333d2b36SAndroid Build Coastguard Workervar updatabilityChecks = []string{"NewApi"} 34*333d2b36SAndroid Build Coastguard Worker 35*333d2b36SAndroid Build Coastguard Workertype LintProperties struct { 36*333d2b36SAndroid Build Coastguard Worker // Controls for running Android Lint on the module. 37*333d2b36SAndroid Build Coastguard Worker Lint struct { 38*333d2b36SAndroid Build Coastguard Worker 39*333d2b36SAndroid Build Coastguard Worker // If true, run Android Lint on the module. Defaults to true. 40*333d2b36SAndroid Build Coastguard Worker Enabled *bool 41*333d2b36SAndroid Build Coastguard Worker 42*333d2b36SAndroid Build Coastguard Worker // Flags to pass to the Android Lint tool. 43*333d2b36SAndroid Build Coastguard Worker Flags []string 44*333d2b36SAndroid Build Coastguard Worker 45*333d2b36SAndroid Build Coastguard Worker // Checks that should be treated as fatal. 46*333d2b36SAndroid Build Coastguard Worker Fatal_checks []string 47*333d2b36SAndroid Build Coastguard Worker 48*333d2b36SAndroid Build Coastguard Worker // Checks that should be treated as errors. 49*333d2b36SAndroid Build Coastguard Worker Error_checks []string 50*333d2b36SAndroid Build Coastguard Worker 51*333d2b36SAndroid Build Coastguard Worker // Checks that should be treated as warnings. 52*333d2b36SAndroid Build Coastguard Worker Warning_checks []string 53*333d2b36SAndroid Build Coastguard Worker 54*333d2b36SAndroid Build Coastguard Worker // Checks that should be skipped. 55*333d2b36SAndroid Build Coastguard Worker Disabled_checks []string 56*333d2b36SAndroid Build Coastguard Worker 57*333d2b36SAndroid Build Coastguard Worker // Modules that provide extra lint checks 58*333d2b36SAndroid Build Coastguard Worker Extra_check_modules []string 59*333d2b36SAndroid Build Coastguard Worker 60*333d2b36SAndroid Build Coastguard Worker // The lint baseline file to use. If specified, lint warnings listed in this file will be 61*333d2b36SAndroid Build Coastguard Worker // suppressed during lint checks. 62*333d2b36SAndroid Build Coastguard Worker Baseline_filename *string 63*333d2b36SAndroid Build Coastguard Worker 64*333d2b36SAndroid Build Coastguard Worker // If true, baselining updatability lint checks (e.g. NewApi) is prohibited. Defaults to false. 65*333d2b36SAndroid Build Coastguard Worker Strict_updatability_linting *bool 66*333d2b36SAndroid Build Coastguard Worker 67*333d2b36SAndroid Build Coastguard Worker // Treat the code in this module as test code for @VisibleForTesting enforcement. 68*333d2b36SAndroid Build Coastguard Worker // This will be true by default for test module types, false otherwise. 69*333d2b36SAndroid Build Coastguard Worker // If soong gets support for testonly, this flag should be replaced with that. 70*333d2b36SAndroid Build Coastguard Worker Test *bool 71*333d2b36SAndroid Build Coastguard Worker 72*333d2b36SAndroid Build Coastguard Worker // Whether to ignore the exit code of Android lint. This is the --exit_code 73*333d2b36SAndroid Build Coastguard Worker // option. Defaults to false. 74*333d2b36SAndroid Build Coastguard Worker Suppress_exit_code *bool 75*333d2b36SAndroid Build Coastguard Worker } 76*333d2b36SAndroid Build Coastguard Worker} 77*333d2b36SAndroid Build Coastguard Worker 78*333d2b36SAndroid Build Coastguard Workertype linter struct { 79*333d2b36SAndroid Build Coastguard Worker name string 80*333d2b36SAndroid Build Coastguard Worker manifest android.Path 81*333d2b36SAndroid Build Coastguard Worker mergedManifest android.Path 82*333d2b36SAndroid Build Coastguard Worker srcs android.Paths 83*333d2b36SAndroid Build Coastguard Worker srcJars android.Paths 84*333d2b36SAndroid Build Coastguard Worker resources android.Paths 85*333d2b36SAndroid Build Coastguard Worker classpath android.Paths 86*333d2b36SAndroid Build Coastguard Worker classes android.Path 87*333d2b36SAndroid Build Coastguard Worker extraLintCheckJars android.Paths 88*333d2b36SAndroid Build Coastguard Worker library bool 89*333d2b36SAndroid Build Coastguard Worker minSdkVersion android.ApiLevel 90*333d2b36SAndroid Build Coastguard Worker targetSdkVersion android.ApiLevel 91*333d2b36SAndroid Build Coastguard Worker compileSdkVersion android.ApiLevel 92*333d2b36SAndroid Build Coastguard Worker compileSdkKind android.SdkKind 93*333d2b36SAndroid Build Coastguard Worker javaLanguageLevel string 94*333d2b36SAndroid Build Coastguard Worker kotlinLanguageLevel string 95*333d2b36SAndroid Build Coastguard Worker properties LintProperties 96*333d2b36SAndroid Build Coastguard Worker extraMainlineLintErrors []string 97*333d2b36SAndroid Build Coastguard Worker compile_data android.Paths 98*333d2b36SAndroid Build Coastguard Worker 99*333d2b36SAndroid Build Coastguard Worker reports android.Paths 100*333d2b36SAndroid Build Coastguard Worker 101*333d2b36SAndroid Build Coastguard Worker buildModuleReportZip bool 102*333d2b36SAndroid Build Coastguard Worker} 103*333d2b36SAndroid Build Coastguard Worker 104*333d2b36SAndroid Build Coastguard Workertype LintDepSets struct { 105*333d2b36SAndroid Build Coastguard Worker HTML, Text, XML, Baseline depset.DepSet[android.Path] 106*333d2b36SAndroid Build Coastguard Worker} 107*333d2b36SAndroid Build Coastguard Worker 108*333d2b36SAndroid Build Coastguard Workertype LintDepSetsBuilder struct { 109*333d2b36SAndroid Build Coastguard Worker HTML, Text, XML, Baseline *depset.Builder[android.Path] 110*333d2b36SAndroid Build Coastguard Worker} 111*333d2b36SAndroid Build Coastguard Worker 112*333d2b36SAndroid Build Coastguard Workerfunc NewLintDepSetBuilder() LintDepSetsBuilder { 113*333d2b36SAndroid Build Coastguard Worker return LintDepSetsBuilder{ 114*333d2b36SAndroid Build Coastguard Worker HTML: depset.NewBuilder[android.Path](depset.POSTORDER), 115*333d2b36SAndroid Build Coastguard Worker Text: depset.NewBuilder[android.Path](depset.POSTORDER), 116*333d2b36SAndroid Build Coastguard Worker XML: depset.NewBuilder[android.Path](depset.POSTORDER), 117*333d2b36SAndroid Build Coastguard Worker Baseline: depset.NewBuilder[android.Path](depset.POSTORDER), 118*333d2b36SAndroid Build Coastguard Worker } 119*333d2b36SAndroid Build Coastguard Worker} 120*333d2b36SAndroid Build Coastguard Worker 121*333d2b36SAndroid Build Coastguard Workerfunc (l LintDepSetsBuilder) Direct(html, text, xml android.Path, baseline android.OptionalPath) LintDepSetsBuilder { 122*333d2b36SAndroid Build Coastguard Worker l.HTML.Direct(html) 123*333d2b36SAndroid Build Coastguard Worker l.Text.Direct(text) 124*333d2b36SAndroid Build Coastguard Worker l.XML.Direct(xml) 125*333d2b36SAndroid Build Coastguard Worker if baseline.Valid() { 126*333d2b36SAndroid Build Coastguard Worker l.Baseline.Direct(baseline.Path()) 127*333d2b36SAndroid Build Coastguard Worker } 128*333d2b36SAndroid Build Coastguard Worker return l 129*333d2b36SAndroid Build Coastguard Worker} 130*333d2b36SAndroid Build Coastguard Worker 131*333d2b36SAndroid Build Coastguard Workerfunc (l LintDepSetsBuilder) Transitive(info *LintInfo) LintDepSetsBuilder { 132*333d2b36SAndroid Build Coastguard Worker l.HTML.Transitive(info.TransitiveHTML) 133*333d2b36SAndroid Build Coastguard Worker l.Text.Transitive(info.TransitiveText) 134*333d2b36SAndroid Build Coastguard Worker l.XML.Transitive(info.TransitiveXML) 135*333d2b36SAndroid Build Coastguard Worker l.Baseline.Transitive(info.TransitiveBaseline) 136*333d2b36SAndroid Build Coastguard Worker return l 137*333d2b36SAndroid Build Coastguard Worker} 138*333d2b36SAndroid Build Coastguard Worker 139*333d2b36SAndroid Build Coastguard Workerfunc (l LintDepSetsBuilder) Build() LintDepSets { 140*333d2b36SAndroid Build Coastguard Worker return LintDepSets{ 141*333d2b36SAndroid Build Coastguard Worker HTML: l.HTML.Build(), 142*333d2b36SAndroid Build Coastguard Worker Text: l.Text.Build(), 143*333d2b36SAndroid Build Coastguard Worker XML: l.XML.Build(), 144*333d2b36SAndroid Build Coastguard Worker Baseline: l.Baseline.Build(), 145*333d2b36SAndroid Build Coastguard Worker } 146*333d2b36SAndroid Build Coastguard Worker} 147*333d2b36SAndroid Build Coastguard Worker 148*333d2b36SAndroid Build Coastguard Workertype lintDatabaseFiles struct { 149*333d2b36SAndroid Build Coastguard Worker apiVersionsModule string 150*333d2b36SAndroid Build Coastguard Worker apiVersionsCopiedName string 151*333d2b36SAndroid Build Coastguard Worker apiVersionsPrebuiltPath string 152*333d2b36SAndroid Build Coastguard Worker annotationsModule string 153*333d2b36SAndroid Build Coastguard Worker annotationCopiedName string 154*333d2b36SAndroid Build Coastguard Worker annotationPrebuiltpath string 155*333d2b36SAndroid Build Coastguard Worker} 156*333d2b36SAndroid Build Coastguard Worker 157*333d2b36SAndroid Build Coastguard Workervar allLintDatabasefiles = map[android.SdkKind]lintDatabaseFiles{ 158*333d2b36SAndroid Build Coastguard Worker android.SdkPublic: { 159*333d2b36SAndroid Build Coastguard Worker apiVersionsModule: "api_versions_public", 160*333d2b36SAndroid Build Coastguard Worker apiVersionsCopiedName: "api_versions_public.xml", 161*333d2b36SAndroid Build Coastguard Worker apiVersionsPrebuiltPath: "prebuilts/sdk/current/public/data/api-versions.xml", 162*333d2b36SAndroid Build Coastguard Worker annotationsModule: "sdk-annotations.zip", 163*333d2b36SAndroid Build Coastguard Worker annotationCopiedName: "annotations-public.zip", 164*333d2b36SAndroid Build Coastguard Worker annotationPrebuiltpath: "prebuilts/sdk/current/public/data/annotations.zip", 165*333d2b36SAndroid Build Coastguard Worker }, 166*333d2b36SAndroid Build Coastguard Worker android.SdkSystem: { 167*333d2b36SAndroid Build Coastguard Worker apiVersionsModule: "api_versions_system", 168*333d2b36SAndroid Build Coastguard Worker apiVersionsCopiedName: "api_versions_system.xml", 169*333d2b36SAndroid Build Coastguard Worker apiVersionsPrebuiltPath: "prebuilts/sdk/current/system/data/api-versions.xml", 170*333d2b36SAndroid Build Coastguard Worker annotationsModule: "sdk-annotations-system.zip", 171*333d2b36SAndroid Build Coastguard Worker annotationCopiedName: "annotations-system.zip", 172*333d2b36SAndroid Build Coastguard Worker annotationPrebuiltpath: "prebuilts/sdk/current/system/data/annotations.zip", 173*333d2b36SAndroid Build Coastguard Worker }, 174*333d2b36SAndroid Build Coastguard Worker android.SdkModule: { 175*333d2b36SAndroid Build Coastguard Worker apiVersionsModule: "api_versions_module_lib", 176*333d2b36SAndroid Build Coastguard Worker apiVersionsCopiedName: "api_versions_module_lib.xml", 177*333d2b36SAndroid Build Coastguard Worker apiVersionsPrebuiltPath: "prebuilts/sdk/current/module-lib/data/api-versions.xml", 178*333d2b36SAndroid Build Coastguard Worker annotationsModule: "sdk-annotations-module-lib.zip", 179*333d2b36SAndroid Build Coastguard Worker annotationCopiedName: "annotations-module-lib.zip", 180*333d2b36SAndroid Build Coastguard Worker annotationPrebuiltpath: "prebuilts/sdk/current/module-lib/data/annotations.zip", 181*333d2b36SAndroid Build Coastguard Worker }, 182*333d2b36SAndroid Build Coastguard Worker android.SdkSystemServer: { 183*333d2b36SAndroid Build Coastguard Worker apiVersionsModule: "api_versions_system_server", 184*333d2b36SAndroid Build Coastguard Worker apiVersionsCopiedName: "api_versions_system_server.xml", 185*333d2b36SAndroid Build Coastguard Worker apiVersionsPrebuiltPath: "prebuilts/sdk/current/system-server/data/api-versions.xml", 186*333d2b36SAndroid Build Coastguard Worker annotationsModule: "sdk-annotations-system-server.zip", 187*333d2b36SAndroid Build Coastguard Worker annotationCopiedName: "annotations-system-server.zip", 188*333d2b36SAndroid Build Coastguard Worker annotationPrebuiltpath: "prebuilts/sdk/current/system-server/data/annotations.zip", 189*333d2b36SAndroid Build Coastguard Worker }, 190*333d2b36SAndroid Build Coastguard Worker} 191*333d2b36SAndroid Build Coastguard Worker 192*333d2b36SAndroid Build Coastguard Workervar LintProvider = blueprint.NewProvider[*LintInfo]() 193*333d2b36SAndroid Build Coastguard Worker 194*333d2b36SAndroid Build Coastguard Workertype LintInfo struct { 195*333d2b36SAndroid Build Coastguard Worker HTML android.Path 196*333d2b36SAndroid Build Coastguard Worker Text android.Path 197*333d2b36SAndroid Build Coastguard Worker XML android.Path 198*333d2b36SAndroid Build Coastguard Worker ReferenceBaseline android.Path 199*333d2b36SAndroid Build Coastguard Worker 200*333d2b36SAndroid Build Coastguard Worker TransitiveHTML depset.DepSet[android.Path] 201*333d2b36SAndroid Build Coastguard Worker TransitiveText depset.DepSet[android.Path] 202*333d2b36SAndroid Build Coastguard Worker TransitiveXML depset.DepSet[android.Path] 203*333d2b36SAndroid Build Coastguard Worker TransitiveBaseline depset.DepSet[android.Path] 204*333d2b36SAndroid Build Coastguard Worker} 205*333d2b36SAndroid Build Coastguard Worker 206*333d2b36SAndroid Build Coastguard Workerfunc (l *linter) enabled() bool { 207*333d2b36SAndroid Build Coastguard Worker return BoolDefault(l.properties.Lint.Enabled, true) 208*333d2b36SAndroid Build Coastguard Worker} 209*333d2b36SAndroid Build Coastguard Worker 210*333d2b36SAndroid Build Coastguard Workerfunc (l *linter) deps(ctx android.BottomUpMutatorContext) { 211*333d2b36SAndroid Build Coastguard Worker if !l.enabled() { 212*333d2b36SAndroid Build Coastguard Worker return 213*333d2b36SAndroid Build Coastguard Worker } 214*333d2b36SAndroid Build Coastguard Worker 215*333d2b36SAndroid Build Coastguard Worker extraCheckModules := l.properties.Lint.Extra_check_modules 216*333d2b36SAndroid Build Coastguard Worker 217*333d2b36SAndroid Build Coastguard Worker if extraCheckModulesEnv := ctx.Config().Getenv("ANDROID_LINT_CHECK_EXTRA_MODULES"); extraCheckModulesEnv != "" { 218*333d2b36SAndroid Build Coastguard Worker extraCheckModules = append(extraCheckModules, strings.Split(extraCheckModulesEnv, ",")...) 219*333d2b36SAndroid Build Coastguard Worker } 220*333d2b36SAndroid Build Coastguard Worker 221*333d2b36SAndroid Build Coastguard Worker ctx.AddFarVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(), 222*333d2b36SAndroid Build Coastguard Worker extraLintCheckTag, extraCheckModules...) 223*333d2b36SAndroid Build Coastguard Worker} 224*333d2b36SAndroid Build Coastguard Worker 225*333d2b36SAndroid Build Coastguard Worker// lintPaths contains the paths to lint's inputs and outputs to make it easier to pass them 226*333d2b36SAndroid Build Coastguard Worker// around. 227*333d2b36SAndroid Build Coastguard Workertype lintPaths struct { 228*333d2b36SAndroid Build Coastguard Worker projectXML android.WritablePath 229*333d2b36SAndroid Build Coastguard Worker configXML android.WritablePath 230*333d2b36SAndroid Build Coastguard Worker cacheDir android.WritablePath 231*333d2b36SAndroid Build Coastguard Worker homeDir android.WritablePath 232*333d2b36SAndroid Build Coastguard Worker srcjarDir android.WritablePath 233*333d2b36SAndroid Build Coastguard Worker} 234*333d2b36SAndroid Build Coastguard Worker 235*333d2b36SAndroid Build Coastguard Workerfunc lintRBEExecStrategy(ctx android.ModuleContext) string { 236*333d2b36SAndroid Build Coastguard Worker return ctx.Config().GetenvWithDefault("RBE_LINT_EXEC_STRATEGY", remoteexec.LocalExecStrategy) 237*333d2b36SAndroid Build Coastguard Worker} 238*333d2b36SAndroid Build Coastguard Worker 239*333d2b36SAndroid Build Coastguard Workerfunc (l *linter) writeLintProjectXML(ctx android.ModuleContext, rule *android.RuleBuilder, srcsList android.Path, 240*333d2b36SAndroid Build Coastguard Worker baselines android.Paths) lintPaths { 241*333d2b36SAndroid Build Coastguard Worker 242*333d2b36SAndroid Build Coastguard Worker projectXMLPath := android.PathForModuleOut(ctx, "lint", "project.xml") 243*333d2b36SAndroid Build Coastguard Worker // Lint looks for a lint.xml file next to the project.xml file, give it one. 244*333d2b36SAndroid Build Coastguard Worker configXMLPath := android.PathForModuleOut(ctx, "lint", "lint.xml") 245*333d2b36SAndroid Build Coastguard Worker cacheDir := android.PathForModuleOut(ctx, "lint", "cache") 246*333d2b36SAndroid Build Coastguard Worker homeDir := android.PathForModuleOut(ctx, "lint", "home") 247*333d2b36SAndroid Build Coastguard Worker 248*333d2b36SAndroid Build Coastguard Worker srcJarDir := android.PathForModuleOut(ctx, "lint", "srcjars") 249*333d2b36SAndroid Build Coastguard Worker srcJarList := zipSyncCmd(ctx, rule, srcJarDir, l.srcJars) 250*333d2b36SAndroid Build Coastguard Worker 251*333d2b36SAndroid Build Coastguard Worker cmd := rule.Command(). 252*333d2b36SAndroid Build Coastguard Worker BuiltTool("lint_project_xml"). 253*333d2b36SAndroid Build Coastguard Worker FlagWithOutput("--project_out ", projectXMLPath). 254*333d2b36SAndroid Build Coastguard Worker FlagWithOutput("--config_out ", configXMLPath). 255*333d2b36SAndroid Build Coastguard Worker FlagWithArg("--name ", ctx.ModuleName()) 256*333d2b36SAndroid Build Coastguard Worker 257*333d2b36SAndroid Build Coastguard Worker if l.library { 258*333d2b36SAndroid Build Coastguard Worker cmd.Flag("--library") 259*333d2b36SAndroid Build Coastguard Worker } 260*333d2b36SAndroid Build Coastguard Worker if proptools.BoolDefault(l.properties.Lint.Test, false) { 261*333d2b36SAndroid Build Coastguard Worker cmd.Flag("--test") 262*333d2b36SAndroid Build Coastguard Worker } 263*333d2b36SAndroid Build Coastguard Worker if l.manifest != nil { 264*333d2b36SAndroid Build Coastguard Worker cmd.FlagWithInput("--manifest ", l.manifest) 265*333d2b36SAndroid Build Coastguard Worker } 266*333d2b36SAndroid Build Coastguard Worker if l.mergedManifest != nil { 267*333d2b36SAndroid Build Coastguard Worker cmd.FlagWithInput("--merged_manifest ", l.mergedManifest) 268*333d2b36SAndroid Build Coastguard Worker } 269*333d2b36SAndroid Build Coastguard Worker 270*333d2b36SAndroid Build Coastguard Worker // TODO(ccross): some of the files in l.srcs are generated sources and should be passed to 271*333d2b36SAndroid Build Coastguard Worker // lint separately. 272*333d2b36SAndroid Build Coastguard Worker cmd.FlagWithInput("--srcs ", srcsList) 273*333d2b36SAndroid Build Coastguard Worker 274*333d2b36SAndroid Build Coastguard Worker cmd.FlagWithInput("--generated_srcs ", srcJarList) 275*333d2b36SAndroid Build Coastguard Worker 276*333d2b36SAndroid Build Coastguard Worker if len(l.resources) > 0 { 277*333d2b36SAndroid Build Coastguard Worker resourcesList := android.PathForModuleOut(ctx, "lint-resources.list") 278*333d2b36SAndroid Build Coastguard Worker cmd.FlagWithRspFileInputList("--resources ", resourcesList, l.resources) 279*333d2b36SAndroid Build Coastguard Worker } 280*333d2b36SAndroid Build Coastguard Worker 281*333d2b36SAndroid Build Coastguard Worker if l.classes != nil { 282*333d2b36SAndroid Build Coastguard Worker cmd.FlagWithInput("--classes ", l.classes) 283*333d2b36SAndroid Build Coastguard Worker } 284*333d2b36SAndroid Build Coastguard Worker 285*333d2b36SAndroid Build Coastguard Worker cmd.FlagForEachInput("--classpath ", l.classpath) 286*333d2b36SAndroid Build Coastguard Worker 287*333d2b36SAndroid Build Coastguard Worker cmd.FlagForEachInput("--extra_checks_jar ", l.extraLintCheckJars) 288*333d2b36SAndroid Build Coastguard Worker 289*333d2b36SAndroid Build Coastguard Worker cmd.FlagWithArg("--root_dir ", "$PWD") 290*333d2b36SAndroid Build Coastguard Worker 291*333d2b36SAndroid Build Coastguard Worker // The cache tag in project.xml is relative to the root dir, or the project.xml file if 292*333d2b36SAndroid Build Coastguard Worker // the root dir is not set. 293*333d2b36SAndroid Build Coastguard Worker cmd.FlagWithArg("--cache_dir ", cacheDir.String()) 294*333d2b36SAndroid Build Coastguard Worker 295*333d2b36SAndroid Build Coastguard Worker cmd.FlagWithInput("@", 296*333d2b36SAndroid Build Coastguard Worker android.PathForSource(ctx, "build/soong/java/lint_defaults.txt")) 297*333d2b36SAndroid Build Coastguard Worker 298*333d2b36SAndroid Build Coastguard Worker cmd.FlagForEachArg("--error_check ", l.extraMainlineLintErrors) 299*333d2b36SAndroid Build Coastguard Worker cmd.FlagForEachArg("--disable_check ", l.properties.Lint.Disabled_checks) 300*333d2b36SAndroid Build Coastguard Worker cmd.FlagForEachArg("--warning_check ", l.properties.Lint.Warning_checks) 301*333d2b36SAndroid Build Coastguard Worker cmd.FlagForEachArg("--error_check ", l.properties.Lint.Error_checks) 302*333d2b36SAndroid Build Coastguard Worker cmd.FlagForEachArg("--fatal_check ", l.properties.Lint.Fatal_checks) 303*333d2b36SAndroid Build Coastguard Worker 304*333d2b36SAndroid Build Coastguard Worker if Bool(l.properties.Lint.Strict_updatability_linting) && len(baselines) > 0 { 305*333d2b36SAndroid Build Coastguard Worker // Verify the module does not baseline issues that endanger safe updatability. 306*333d2b36SAndroid Build Coastguard Worker strictUpdatabilityChecksOutputFile := VerifyStrictUpdatabilityChecks(ctx, baselines) 307*333d2b36SAndroid Build Coastguard Worker cmd.Validation(strictUpdatabilityChecksOutputFile) 308*333d2b36SAndroid Build Coastguard Worker } 309*333d2b36SAndroid Build Coastguard Worker 310*333d2b36SAndroid Build Coastguard Worker return lintPaths{ 311*333d2b36SAndroid Build Coastguard Worker projectXML: projectXMLPath, 312*333d2b36SAndroid Build Coastguard Worker configXML: configXMLPath, 313*333d2b36SAndroid Build Coastguard Worker cacheDir: cacheDir, 314*333d2b36SAndroid Build Coastguard Worker homeDir: homeDir, 315*333d2b36SAndroid Build Coastguard Worker } 316*333d2b36SAndroid Build Coastguard Worker 317*333d2b36SAndroid Build Coastguard Worker} 318*333d2b36SAndroid Build Coastguard Worker 319*333d2b36SAndroid Build Coastguard Workerfunc VerifyStrictUpdatabilityChecks(ctx android.ModuleContext, baselines android.Paths) android.Path { 320*333d2b36SAndroid Build Coastguard Worker rule := android.NewRuleBuilder(pctx, ctx) 321*333d2b36SAndroid Build Coastguard Worker baselineRspFile := android.PathForModuleOut(ctx, "lint_strict_updatability_check_baselines.rsp") 322*333d2b36SAndroid Build Coastguard Worker outputFile := android.PathForModuleOut(ctx, "lint_strict_updatability_check.stamp") 323*333d2b36SAndroid Build Coastguard Worker rule.Command().Text("rm -f").Output(outputFile) 324*333d2b36SAndroid Build Coastguard Worker rule.Command(). 325*333d2b36SAndroid Build Coastguard Worker BuiltTool("lint_strict_updatability_checks"). 326*333d2b36SAndroid Build Coastguard Worker FlagWithArg("--name ", ctx.ModuleName()). 327*333d2b36SAndroid Build Coastguard Worker FlagWithRspFileInputList("--baselines ", baselineRspFile, baselines). 328*333d2b36SAndroid Build Coastguard Worker FlagForEachArg("--disallowed_issues ", updatabilityChecks) 329*333d2b36SAndroid Build Coastguard Worker rule.Command().Text("touch").Output(outputFile) 330*333d2b36SAndroid Build Coastguard Worker rule.Build("lint_strict_updatability_checks", "lint strict updatability checks") 331*333d2b36SAndroid Build Coastguard Worker 332*333d2b36SAndroid Build Coastguard Worker return outputFile 333*333d2b36SAndroid Build Coastguard Worker} 334*333d2b36SAndroid Build Coastguard Worker 335*333d2b36SAndroid Build Coastguard Worker// generateManifest adds a command to the rule to write a simple manifest that contains the 336*333d2b36SAndroid Build Coastguard Worker// minSdkVersion and targetSdkVersion for modules (like java_library) that don't have a manifest. 337*333d2b36SAndroid Build Coastguard Workerfunc (l *linter) generateManifest(ctx android.ModuleContext, rule *android.RuleBuilder) android.WritablePath { 338*333d2b36SAndroid Build Coastguard Worker manifestPath := android.PathForModuleOut(ctx, "lint", "AndroidManifest.xml") 339*333d2b36SAndroid Build Coastguard Worker 340*333d2b36SAndroid Build Coastguard Worker rule.Command().Text("("). 341*333d2b36SAndroid Build Coastguard Worker Text(`echo "<?xml version='1.0' encoding='utf-8'?>" &&`). 342*333d2b36SAndroid Build Coastguard Worker Text(`echo "<manifest xmlns:android='http://schemas.android.com/apk/res/android'" &&`). 343*333d2b36SAndroid Build Coastguard Worker Text(`echo " android:versionCode='1' android:versionName='1' >" &&`). 344*333d2b36SAndroid Build Coastguard Worker Textf(`echo " <uses-sdk android:minSdkVersion='%s' android:targetSdkVersion='%s'/>" &&`, 345*333d2b36SAndroid Build Coastguard Worker l.minSdkVersion.String(), l.targetSdkVersion.String()). 346*333d2b36SAndroid Build Coastguard Worker Text(`echo "</manifest>"`). 347*333d2b36SAndroid Build Coastguard Worker Text(") >").Output(manifestPath) 348*333d2b36SAndroid Build Coastguard Worker 349*333d2b36SAndroid Build Coastguard Worker return manifestPath 350*333d2b36SAndroid Build Coastguard Worker} 351*333d2b36SAndroid Build Coastguard Worker 352*333d2b36SAndroid Build Coastguard Workerfunc (l *linter) lint(ctx android.ModuleContext) { 353*333d2b36SAndroid Build Coastguard Worker if !l.enabled() { 354*333d2b36SAndroid Build Coastguard Worker return 355*333d2b36SAndroid Build Coastguard Worker } 356*333d2b36SAndroid Build Coastguard Worker 357*333d2b36SAndroid Build Coastguard Worker for _, flag := range l.properties.Lint.Flags { 358*333d2b36SAndroid Build Coastguard Worker if strings.Contains(flag, "--disable") || strings.Contains(flag, "--enable") || strings.Contains(flag, "--check") { 359*333d2b36SAndroid Build Coastguard Worker ctx.PropertyErrorf("lint.flags", "Don't use --disable, --enable, or --check in the flags field, instead use the dedicated disabled_checks, warning_checks, error_checks, or fatal_checks fields") 360*333d2b36SAndroid Build Coastguard Worker } 361*333d2b36SAndroid Build Coastguard Worker } 362*333d2b36SAndroid Build Coastguard Worker 363*333d2b36SAndroid Build Coastguard Worker if l.minSdkVersion.CompareTo(l.compileSdkVersion) == -1 { 364*333d2b36SAndroid Build Coastguard Worker l.extraMainlineLintErrors = append(l.extraMainlineLintErrors, updatabilityChecks...) 365*333d2b36SAndroid Build Coastguard Worker // Skip lint warning checks for NewApi warnings for libcore where they come from source 366*333d2b36SAndroid Build Coastguard Worker // files that reference the API they are adding (b/208656169). 367*333d2b36SAndroid Build Coastguard Worker if !strings.HasPrefix(ctx.ModuleDir(), "libcore") { 368*333d2b36SAndroid Build Coastguard Worker _, filtered := android.FilterList(l.properties.Lint.Warning_checks, updatabilityChecks) 369*333d2b36SAndroid Build Coastguard Worker 370*333d2b36SAndroid Build Coastguard Worker if len(filtered) != 0 { 371*333d2b36SAndroid Build Coastguard Worker ctx.PropertyErrorf("lint.warning_checks", 372*333d2b36SAndroid Build Coastguard Worker "Can't treat %v checks as warnings if min_sdk_version is different from sdk_version.", filtered) 373*333d2b36SAndroid Build Coastguard Worker } 374*333d2b36SAndroid Build Coastguard Worker } 375*333d2b36SAndroid Build Coastguard Worker 376*333d2b36SAndroid Build Coastguard Worker _, filtered := android.FilterList(l.properties.Lint.Disabled_checks, updatabilityChecks) 377*333d2b36SAndroid Build Coastguard Worker if len(filtered) != 0 { 378*333d2b36SAndroid Build Coastguard Worker ctx.PropertyErrorf("lint.disabled_checks", 379*333d2b36SAndroid Build Coastguard Worker "Can't disable %v checks if min_sdk_version is different from sdk_version.", filtered) 380*333d2b36SAndroid Build Coastguard Worker } 381*333d2b36SAndroid Build Coastguard Worker 382*333d2b36SAndroid Build Coastguard Worker // TODO(b/238784089): Remove this workaround when the NewApi issues have been addressed in PermissionController 383*333d2b36SAndroid Build Coastguard Worker if ctx.ModuleName() == "PermissionController" { 384*333d2b36SAndroid Build Coastguard Worker l.extraMainlineLintErrors = android.FilterListPred(l.extraMainlineLintErrors, func(s string) bool { 385*333d2b36SAndroid Build Coastguard Worker return s != "NewApi" 386*333d2b36SAndroid Build Coastguard Worker }) 387*333d2b36SAndroid Build Coastguard Worker l.properties.Lint.Warning_checks = append(l.properties.Lint.Warning_checks, "NewApi") 388*333d2b36SAndroid Build Coastguard Worker } 389*333d2b36SAndroid Build Coastguard Worker } 390*333d2b36SAndroid Build Coastguard Worker 391*333d2b36SAndroid Build Coastguard Worker extraLintCheckModules := ctx.GetDirectDepsWithTag(extraLintCheckTag) 392*333d2b36SAndroid Build Coastguard Worker for _, extraLintCheckModule := range extraLintCheckModules { 393*333d2b36SAndroid Build Coastguard Worker if dep, ok := android.OtherModuleProvider(ctx, extraLintCheckModule, JavaInfoProvider); ok { 394*333d2b36SAndroid Build Coastguard Worker l.extraLintCheckJars = append(l.extraLintCheckJars, dep.ImplementationAndResourcesJars...) 395*333d2b36SAndroid Build Coastguard Worker } else { 396*333d2b36SAndroid Build Coastguard Worker ctx.PropertyErrorf("lint.extra_check_modules", 397*333d2b36SAndroid Build Coastguard Worker "%s is not a java module", ctx.OtherModuleName(extraLintCheckModule)) 398*333d2b36SAndroid Build Coastguard Worker } 399*333d2b36SAndroid Build Coastguard Worker } 400*333d2b36SAndroid Build Coastguard Worker 401*333d2b36SAndroid Build Coastguard Worker l.extraLintCheckJars = append(l.extraLintCheckJars, android.PathForSource(ctx, 402*333d2b36SAndroid Build Coastguard Worker "prebuilts/cmdline-tools/AndroidGlobalLintChecker.jar")) 403*333d2b36SAndroid Build Coastguard Worker 404*333d2b36SAndroid Build Coastguard Worker var baseline android.OptionalPath 405*333d2b36SAndroid Build Coastguard Worker if l.properties.Lint.Baseline_filename != nil { 406*333d2b36SAndroid Build Coastguard Worker baseline = android.OptionalPathForPath(android.PathForModuleSrc(ctx, *l.properties.Lint.Baseline_filename)) 407*333d2b36SAndroid Build Coastguard Worker } 408*333d2b36SAndroid Build Coastguard Worker 409*333d2b36SAndroid Build Coastguard Worker html := android.PathForModuleOut(ctx, "lint", "lint-report.html") 410*333d2b36SAndroid Build Coastguard Worker text := android.PathForModuleOut(ctx, "lint", "lint-report.txt") 411*333d2b36SAndroid Build Coastguard Worker xml := android.PathForModuleOut(ctx, "lint", "lint-report.xml") 412*333d2b36SAndroid Build Coastguard Worker referenceBaseline := android.PathForModuleOut(ctx, "lint", "lint-baseline.xml") 413*333d2b36SAndroid Build Coastguard Worker 414*333d2b36SAndroid Build Coastguard Worker depSetsBuilder := NewLintDepSetBuilder().Direct(html, text, xml, baseline) 415*333d2b36SAndroid Build Coastguard Worker 416*333d2b36SAndroid Build Coastguard Worker ctx.VisitDirectDepsWithTag(staticLibTag, func(dep android.Module) { 417*333d2b36SAndroid Build Coastguard Worker if info, ok := android.OtherModuleProvider(ctx, dep, LintProvider); ok { 418*333d2b36SAndroid Build Coastguard Worker depSetsBuilder.Transitive(info) 419*333d2b36SAndroid Build Coastguard Worker } 420*333d2b36SAndroid Build Coastguard Worker }) 421*333d2b36SAndroid Build Coastguard Worker 422*333d2b36SAndroid Build Coastguard Worker depSets := depSetsBuilder.Build() 423*333d2b36SAndroid Build Coastguard Worker 424*333d2b36SAndroid Build Coastguard Worker rule := android.NewRuleBuilder(pctx, ctx). 425*333d2b36SAndroid Build Coastguard Worker Sbox(android.PathForModuleOut(ctx, "lint"), 426*333d2b36SAndroid Build Coastguard Worker android.PathForModuleOut(ctx, "lint.sbox.textproto")). 427*333d2b36SAndroid Build Coastguard Worker SandboxInputs() 428*333d2b36SAndroid Build Coastguard Worker 429*333d2b36SAndroid Build Coastguard Worker if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_LINT") { 430*333d2b36SAndroid Build Coastguard Worker pool := ctx.Config().GetenvWithDefault("RBE_LINT_POOL", "java16") 431*333d2b36SAndroid Build Coastguard Worker rule.Remoteable(android.RemoteRuleSupports{RBE: true}) 432*333d2b36SAndroid Build Coastguard Worker rule.Rewrapper(&remoteexec.REParams{ 433*333d2b36SAndroid Build Coastguard Worker Labels: map[string]string{"type": "tool", "name": "lint"}, 434*333d2b36SAndroid Build Coastguard Worker ExecStrategy: lintRBEExecStrategy(ctx), 435*333d2b36SAndroid Build Coastguard Worker ToolchainInputs: []string{config.JavaCmd(ctx).String()}, 436*333d2b36SAndroid Build Coastguard Worker Platform: map[string]string{remoteexec.PoolKey: pool}, 437*333d2b36SAndroid Build Coastguard Worker }) 438*333d2b36SAndroid Build Coastguard Worker } 439*333d2b36SAndroid Build Coastguard Worker 440*333d2b36SAndroid Build Coastguard Worker if l.manifest == nil { 441*333d2b36SAndroid Build Coastguard Worker manifest := l.generateManifest(ctx, rule) 442*333d2b36SAndroid Build Coastguard Worker l.manifest = manifest 443*333d2b36SAndroid Build Coastguard Worker rule.Temporary(manifest) 444*333d2b36SAndroid Build Coastguard Worker } 445*333d2b36SAndroid Build Coastguard Worker 446*333d2b36SAndroid Build Coastguard Worker srcsList := android.PathForModuleOut(ctx, "lint", "lint-srcs.list") 447*333d2b36SAndroid Build Coastguard Worker srcsListRsp := android.PathForModuleOut(ctx, "lint-srcs.list.rsp") 448*333d2b36SAndroid Build Coastguard Worker rule.Command().Text("cp").FlagWithRspFileInputList("", srcsListRsp, l.srcs).Output(srcsList).Implicits(l.compile_data) 449*333d2b36SAndroid Build Coastguard Worker 450*333d2b36SAndroid Build Coastguard Worker baselines := depSets.Baseline.ToList() 451*333d2b36SAndroid Build Coastguard Worker 452*333d2b36SAndroid Build Coastguard Worker lintPaths := l.writeLintProjectXML(ctx, rule, srcsList, baselines) 453*333d2b36SAndroid Build Coastguard Worker 454*333d2b36SAndroid Build Coastguard Worker rule.Command().Text("rm -rf").Flag(lintPaths.cacheDir.String()).Flag(lintPaths.homeDir.String()) 455*333d2b36SAndroid Build Coastguard Worker rule.Command().Text("mkdir -p").Flag(lintPaths.cacheDir.String()).Flag(lintPaths.homeDir.String()) 456*333d2b36SAndroid Build Coastguard Worker rule.Command().Text("rm -f").Output(html).Output(text).Output(xml) 457*333d2b36SAndroid Build Coastguard Worker 458*333d2b36SAndroid Build Coastguard Worker files, ok := allLintDatabasefiles[l.compileSdkKind] 459*333d2b36SAndroid Build Coastguard Worker if !ok { 460*333d2b36SAndroid Build Coastguard Worker files = allLintDatabasefiles[android.SdkPublic] 461*333d2b36SAndroid Build Coastguard Worker } 462*333d2b36SAndroid Build Coastguard Worker var annotationsZipPath, apiVersionsXMLPath android.Path 463*333d2b36SAndroid Build Coastguard Worker if ctx.Config().AlwaysUsePrebuiltSdks() { 464*333d2b36SAndroid Build Coastguard Worker annotationsZipPath = android.PathForSource(ctx, files.annotationPrebuiltpath) 465*333d2b36SAndroid Build Coastguard Worker apiVersionsXMLPath = android.PathForSource(ctx, files.apiVersionsPrebuiltPath) 466*333d2b36SAndroid Build Coastguard Worker } else { 467*333d2b36SAndroid Build Coastguard Worker annotationsZipPath = copiedLintDatabaseFilesPath(ctx, files.annotationCopiedName) 468*333d2b36SAndroid Build Coastguard Worker apiVersionsXMLPath = copiedLintDatabaseFilesPath(ctx, files.apiVersionsCopiedName) 469*333d2b36SAndroid Build Coastguard Worker } 470*333d2b36SAndroid Build Coastguard Worker 471*333d2b36SAndroid Build Coastguard Worker cmd := rule.Command() 472*333d2b36SAndroid Build Coastguard Worker 473*333d2b36SAndroid Build Coastguard Worker cmd.Flag(`JAVA_OPTS="-Xmx3072m --add-opens java.base/java.util=ALL-UNNAMED"`). 474*333d2b36SAndroid Build Coastguard Worker FlagWithArg("ANDROID_SDK_HOME=", lintPaths.homeDir.String()). 475*333d2b36SAndroid Build Coastguard Worker FlagWithInput("SDK_ANNOTATIONS=", annotationsZipPath). 476*333d2b36SAndroid Build Coastguard Worker FlagWithInput("LINT_OPTS=-DLINT_API_DATABASE=", apiVersionsXMLPath) 477*333d2b36SAndroid Build Coastguard Worker 478*333d2b36SAndroid Build Coastguard Worker cmd.BuiltTool("lint").ImplicitTool(ctx.Config().HostJavaToolPath(ctx, "lint.jar")). 479*333d2b36SAndroid Build Coastguard Worker Flag("--quiet"). 480*333d2b36SAndroid Build Coastguard Worker Flag("--include-aosp-issues"). 481*333d2b36SAndroid Build Coastguard Worker FlagWithInput("--project ", lintPaths.projectXML). 482*333d2b36SAndroid Build Coastguard Worker FlagWithInput("--config ", lintPaths.configXML). 483*333d2b36SAndroid Build Coastguard Worker FlagWithOutput("--html ", html). 484*333d2b36SAndroid Build Coastguard Worker FlagWithOutput("--text ", text). 485*333d2b36SAndroid Build Coastguard Worker FlagWithOutput("--xml ", xml). 486*333d2b36SAndroid Build Coastguard Worker FlagWithArg("--compile-sdk-version ", l.compileSdkVersion.String()). 487*333d2b36SAndroid Build Coastguard Worker FlagWithArg("--java-language-level ", l.javaLanguageLevel). 488*333d2b36SAndroid Build Coastguard Worker FlagWithArg("--kotlin-language-level ", l.kotlinLanguageLevel). 489*333d2b36SAndroid Build Coastguard Worker FlagWithArg("--url ", fmt.Sprintf(".=.,%s=out", android.PathForOutput(ctx).String())). 490*333d2b36SAndroid Build Coastguard Worker Flag("--apply-suggestions"). // applies suggested fixes to files in the sandbox 491*333d2b36SAndroid Build Coastguard Worker Flags(l.properties.Lint.Flags). 492*333d2b36SAndroid Build Coastguard Worker Implicit(annotationsZipPath). 493*333d2b36SAndroid Build Coastguard Worker Implicit(apiVersionsXMLPath) 494*333d2b36SAndroid Build Coastguard Worker 495*333d2b36SAndroid Build Coastguard Worker rule.Temporary(lintPaths.projectXML) 496*333d2b36SAndroid Build Coastguard Worker rule.Temporary(lintPaths.configXML) 497*333d2b36SAndroid Build Coastguard Worker 498*333d2b36SAndroid Build Coastguard Worker suppressExitCode := BoolDefault(l.properties.Lint.Suppress_exit_code, false) 499*333d2b36SAndroid Build Coastguard Worker if exitCode := ctx.Config().Getenv("ANDROID_LINT_SUPPRESS_EXIT_CODE"); exitCode == "" && !suppressExitCode { 500*333d2b36SAndroid Build Coastguard Worker cmd.Flag("--exitcode") 501*333d2b36SAndroid Build Coastguard Worker } 502*333d2b36SAndroid Build Coastguard Worker 503*333d2b36SAndroid Build Coastguard Worker if checkOnly := ctx.Config().Getenv("ANDROID_LINT_CHECK"); checkOnly != "" { 504*333d2b36SAndroid Build Coastguard Worker cmd.FlagWithArg("--check ", checkOnly) 505*333d2b36SAndroid Build Coastguard Worker } 506*333d2b36SAndroid Build Coastguard Worker 507*333d2b36SAndroid Build Coastguard Worker if baseline.Valid() { 508*333d2b36SAndroid Build Coastguard Worker cmd.FlagWithInput("--baseline ", baseline.Path()) 509*333d2b36SAndroid Build Coastguard Worker } 510*333d2b36SAndroid Build Coastguard Worker 511*333d2b36SAndroid Build Coastguard Worker cmd.FlagWithOutput("--write-reference-baseline ", referenceBaseline) 512*333d2b36SAndroid Build Coastguard Worker 513*333d2b36SAndroid Build Coastguard Worker cmd.Text("; EXITCODE=$?; ") 514*333d2b36SAndroid Build Coastguard Worker 515*333d2b36SAndroid Build Coastguard Worker // The sources in the sandbox may have been modified by --apply-suggestions, zip them up and 516*333d2b36SAndroid Build Coastguard Worker // export them out of the sandbox. Do this before exiting so that the suggestions exit even after 517*333d2b36SAndroid Build Coastguard Worker // a fatal error. 518*333d2b36SAndroid Build Coastguard Worker cmd.BuiltTool("soong_zip"). 519*333d2b36SAndroid Build Coastguard Worker FlagWithOutput("-o ", android.PathForModuleOut(ctx, "lint", "suggested-fixes.zip")). 520*333d2b36SAndroid Build Coastguard Worker FlagWithArg("-C ", cmd.PathForInput(android.PathForSource(ctx))). 521*333d2b36SAndroid Build Coastguard Worker FlagWithInput("-r ", srcsList) 522*333d2b36SAndroid Build Coastguard Worker 523*333d2b36SAndroid Build Coastguard Worker cmd.Text("; if [ $EXITCODE != 0 ]; then if [ -e").Input(text).Text("]; then cat").Input(text).Text("; fi; exit $EXITCODE; fi") 524*333d2b36SAndroid Build Coastguard Worker 525*333d2b36SAndroid Build Coastguard Worker rule.Command().Text("rm -rf").Flag(lintPaths.cacheDir.String()).Flag(lintPaths.homeDir.String()) 526*333d2b36SAndroid Build Coastguard Worker 527*333d2b36SAndroid Build Coastguard Worker // The HTML output contains a date, remove it to make the output deterministic. 528*333d2b36SAndroid Build Coastguard Worker rule.Command().Text(`sed -i.tmp -e 's|Check performed at .*\(</nav>\)|\1|'`).Output(html) 529*333d2b36SAndroid Build Coastguard Worker 530*333d2b36SAndroid Build Coastguard Worker rule.Build("lint", "lint") 531*333d2b36SAndroid Build Coastguard Worker 532*333d2b36SAndroid Build Coastguard Worker android.SetProvider(ctx, LintProvider, &LintInfo{ 533*333d2b36SAndroid Build Coastguard Worker HTML: html, 534*333d2b36SAndroid Build Coastguard Worker Text: text, 535*333d2b36SAndroid Build Coastguard Worker XML: xml, 536*333d2b36SAndroid Build Coastguard Worker ReferenceBaseline: referenceBaseline, 537*333d2b36SAndroid Build Coastguard Worker 538*333d2b36SAndroid Build Coastguard Worker TransitiveHTML: depSets.HTML, 539*333d2b36SAndroid Build Coastguard Worker TransitiveText: depSets.Text, 540*333d2b36SAndroid Build Coastguard Worker TransitiveXML: depSets.XML, 541*333d2b36SAndroid Build Coastguard Worker TransitiveBaseline: depSets.Baseline, 542*333d2b36SAndroid Build Coastguard Worker }) 543*333d2b36SAndroid Build Coastguard Worker 544*333d2b36SAndroid Build Coastguard Worker if l.buildModuleReportZip { 545*333d2b36SAndroid Build Coastguard Worker l.reports = BuildModuleLintReportZips(ctx, depSets, nil) 546*333d2b36SAndroid Build Coastguard Worker } 547*333d2b36SAndroid Build Coastguard Worker 548*333d2b36SAndroid Build Coastguard Worker // Create a per-module phony target to run the lint check. 549*333d2b36SAndroid Build Coastguard Worker phonyName := ctx.ModuleName() + "-lint" 550*333d2b36SAndroid Build Coastguard Worker ctx.Phony(phonyName, xml) 551*333d2b36SAndroid Build Coastguard Worker 552*333d2b36SAndroid Build Coastguard Worker ctx.SetOutputFiles(android.Paths{xml}, ".lint") 553*333d2b36SAndroid Build Coastguard Worker} 554*333d2b36SAndroid Build Coastguard Worker 555*333d2b36SAndroid Build Coastguard Workerfunc BuildModuleLintReportZips(ctx android.ModuleContext, depSets LintDepSets, validations android.Paths) android.Paths { 556*333d2b36SAndroid Build Coastguard Worker htmlList := android.SortedUniquePaths(depSets.HTML.ToList()) 557*333d2b36SAndroid Build Coastguard Worker textList := android.SortedUniquePaths(depSets.Text.ToList()) 558*333d2b36SAndroid Build Coastguard Worker xmlList := android.SortedUniquePaths(depSets.XML.ToList()) 559*333d2b36SAndroid Build Coastguard Worker 560*333d2b36SAndroid Build Coastguard Worker if len(htmlList) == 0 && len(textList) == 0 && len(xmlList) == 0 { 561*333d2b36SAndroid Build Coastguard Worker return nil 562*333d2b36SAndroid Build Coastguard Worker } 563*333d2b36SAndroid Build Coastguard Worker 564*333d2b36SAndroid Build Coastguard Worker htmlZip := android.PathForModuleOut(ctx, "lint-report-html.zip") 565*333d2b36SAndroid Build Coastguard Worker lintZip(ctx, htmlList, htmlZip, validations) 566*333d2b36SAndroid Build Coastguard Worker 567*333d2b36SAndroid Build Coastguard Worker textZip := android.PathForModuleOut(ctx, "lint-report-text.zip") 568*333d2b36SAndroid Build Coastguard Worker lintZip(ctx, textList, textZip, validations) 569*333d2b36SAndroid Build Coastguard Worker 570*333d2b36SAndroid Build Coastguard Worker xmlZip := android.PathForModuleOut(ctx, "lint-report-xml.zip") 571*333d2b36SAndroid Build Coastguard Worker lintZip(ctx, xmlList, xmlZip, validations) 572*333d2b36SAndroid Build Coastguard Worker 573*333d2b36SAndroid Build Coastguard Worker return android.Paths{htmlZip, textZip, xmlZip} 574*333d2b36SAndroid Build Coastguard Worker} 575*333d2b36SAndroid Build Coastguard Worker 576*333d2b36SAndroid Build Coastguard Workertype lintSingleton struct { 577*333d2b36SAndroid Build Coastguard Worker htmlZip android.WritablePath 578*333d2b36SAndroid Build Coastguard Worker textZip android.WritablePath 579*333d2b36SAndroid Build Coastguard Worker xmlZip android.WritablePath 580*333d2b36SAndroid Build Coastguard Worker referenceBaselineZip android.WritablePath 581*333d2b36SAndroid Build Coastguard Worker} 582*333d2b36SAndroid Build Coastguard Worker 583*333d2b36SAndroid Build Coastguard Workerfunc (l *lintSingleton) GenerateBuildActions(ctx android.SingletonContext) { 584*333d2b36SAndroid Build Coastguard Worker l.generateLintReportZips(ctx) 585*333d2b36SAndroid Build Coastguard Worker l.copyLintDependencies(ctx) 586*333d2b36SAndroid Build Coastguard Worker} 587*333d2b36SAndroid Build Coastguard Worker 588*333d2b36SAndroid Build Coastguard Workerfunc findModuleOrErr(ctx android.SingletonContext, moduleName string) android.Module { 589*333d2b36SAndroid Build Coastguard Worker var res android.Module 590*333d2b36SAndroid Build Coastguard Worker ctx.VisitAllModules(func(m android.Module) { 591*333d2b36SAndroid Build Coastguard Worker if ctx.ModuleName(m) == moduleName { 592*333d2b36SAndroid Build Coastguard Worker if res == nil { 593*333d2b36SAndroid Build Coastguard Worker res = m 594*333d2b36SAndroid Build Coastguard Worker } else { 595*333d2b36SAndroid Build Coastguard Worker ctx.Errorf("lint: multiple %s modules found: %s and %s", moduleName, 596*333d2b36SAndroid Build Coastguard Worker ctx.ModuleSubDir(m), ctx.ModuleSubDir(res)) 597*333d2b36SAndroid Build Coastguard Worker } 598*333d2b36SAndroid Build Coastguard Worker } 599*333d2b36SAndroid Build Coastguard Worker }) 600*333d2b36SAndroid Build Coastguard Worker return res 601*333d2b36SAndroid Build Coastguard Worker} 602*333d2b36SAndroid Build Coastguard Worker 603*333d2b36SAndroid Build Coastguard Workerfunc (l *lintSingleton) copyLintDependencies(ctx android.SingletonContext) { 604*333d2b36SAndroid Build Coastguard Worker if ctx.Config().AlwaysUsePrebuiltSdks() { 605*333d2b36SAndroid Build Coastguard Worker return 606*333d2b36SAndroid Build Coastguard Worker } 607*333d2b36SAndroid Build Coastguard Worker 608*333d2b36SAndroid Build Coastguard Worker for _, sdk := range android.SortedKeys(allLintDatabasefiles) { 609*333d2b36SAndroid Build Coastguard Worker files := allLintDatabasefiles[sdk] 610*333d2b36SAndroid Build Coastguard Worker apiVersionsDb := findModuleOrErr(ctx, files.apiVersionsModule) 611*333d2b36SAndroid Build Coastguard Worker if apiVersionsDb == nil { 612*333d2b36SAndroid Build Coastguard Worker if !ctx.Config().AllowMissingDependencies() { 613*333d2b36SAndroid Build Coastguard Worker ctx.Errorf("lint: missing module %s", files.apiVersionsModule) 614*333d2b36SAndroid Build Coastguard Worker } 615*333d2b36SAndroid Build Coastguard Worker return 616*333d2b36SAndroid Build Coastguard Worker } 617*333d2b36SAndroid Build Coastguard Worker 618*333d2b36SAndroid Build Coastguard Worker sdkAnnotations := findModuleOrErr(ctx, files.annotationsModule) 619*333d2b36SAndroid Build Coastguard Worker if sdkAnnotations == nil { 620*333d2b36SAndroid Build Coastguard Worker if !ctx.Config().AllowMissingDependencies() { 621*333d2b36SAndroid Build Coastguard Worker ctx.Errorf("lint: missing module %s", files.annotationsModule) 622*333d2b36SAndroid Build Coastguard Worker } 623*333d2b36SAndroid Build Coastguard Worker return 624*333d2b36SAndroid Build Coastguard Worker } 625*333d2b36SAndroid Build Coastguard Worker 626*333d2b36SAndroid Build Coastguard Worker ctx.Build(pctx, android.BuildParams{ 627*333d2b36SAndroid Build Coastguard Worker Rule: android.CpIfChanged, 628*333d2b36SAndroid Build Coastguard Worker Input: android.OutputFileForModule(ctx, sdkAnnotations, ""), 629*333d2b36SAndroid Build Coastguard Worker Output: copiedLintDatabaseFilesPath(ctx, files.annotationCopiedName), 630*333d2b36SAndroid Build Coastguard Worker }) 631*333d2b36SAndroid Build Coastguard Worker 632*333d2b36SAndroid Build Coastguard Worker ctx.Build(pctx, android.BuildParams{ 633*333d2b36SAndroid Build Coastguard Worker Rule: android.CpIfChanged, 634*333d2b36SAndroid Build Coastguard Worker Input: android.OutputFileForModule(ctx, apiVersionsDb, ".api_versions.xml"), 635*333d2b36SAndroid Build Coastguard Worker Output: copiedLintDatabaseFilesPath(ctx, files.apiVersionsCopiedName), 636*333d2b36SAndroid Build Coastguard Worker }) 637*333d2b36SAndroid Build Coastguard Worker } 638*333d2b36SAndroid Build Coastguard Worker} 639*333d2b36SAndroid Build Coastguard Worker 640*333d2b36SAndroid Build Coastguard Workerfunc copiedLintDatabaseFilesPath(ctx android.PathContext, name string) android.WritablePath { 641*333d2b36SAndroid Build Coastguard Worker return android.PathForOutput(ctx, "lint", name) 642*333d2b36SAndroid Build Coastguard Worker} 643*333d2b36SAndroid Build Coastguard Worker 644*333d2b36SAndroid Build Coastguard Workerfunc (l *lintSingleton) generateLintReportZips(ctx android.SingletonContext) { 645*333d2b36SAndroid Build Coastguard Worker if ctx.Config().UnbundledBuild() { 646*333d2b36SAndroid Build Coastguard Worker return 647*333d2b36SAndroid Build Coastguard Worker } 648*333d2b36SAndroid Build Coastguard Worker 649*333d2b36SAndroid Build Coastguard Worker var outputs []*LintInfo 650*333d2b36SAndroid Build Coastguard Worker var dirs []string 651*333d2b36SAndroid Build Coastguard Worker ctx.VisitAllModules(func(m android.Module) { 652*333d2b36SAndroid Build Coastguard Worker if ctx.Config().KatiEnabled() && !m.ExportedToMake() { 653*333d2b36SAndroid Build Coastguard Worker return 654*333d2b36SAndroid Build Coastguard Worker } 655*333d2b36SAndroid Build Coastguard Worker 656*333d2b36SAndroid Build Coastguard Worker if apex, ok := m.(android.ApexModule); ok && apex.NotAvailableForPlatform() { 657*333d2b36SAndroid Build Coastguard Worker apexInfo, _ := android.OtherModuleProvider(ctx, m, android.ApexInfoProvider) 658*333d2b36SAndroid Build Coastguard Worker if apexInfo.IsForPlatform() { 659*333d2b36SAndroid Build Coastguard Worker // There are stray platform variants of modules in apexes that are not available for 660*333d2b36SAndroid Build Coastguard Worker // the platform, and they sometimes can't be built. Don't depend on them. 661*333d2b36SAndroid Build Coastguard Worker return 662*333d2b36SAndroid Build Coastguard Worker } 663*333d2b36SAndroid Build Coastguard Worker } 664*333d2b36SAndroid Build Coastguard Worker 665*333d2b36SAndroid Build Coastguard Worker if lintInfo, ok := android.OtherModuleProvider(ctx, m, LintProvider); ok { 666*333d2b36SAndroid Build Coastguard Worker outputs = append(outputs, lintInfo) 667*333d2b36SAndroid Build Coastguard Worker } 668*333d2b36SAndroid Build Coastguard Worker }) 669*333d2b36SAndroid Build Coastguard Worker 670*333d2b36SAndroid Build Coastguard Worker dirs = android.SortedUniqueStrings(dirs) 671*333d2b36SAndroid Build Coastguard Worker 672*333d2b36SAndroid Build Coastguard Worker zip := func(outputPath android.WritablePath, get func(*LintInfo) android.Path) { 673*333d2b36SAndroid Build Coastguard Worker var paths android.Paths 674*333d2b36SAndroid Build Coastguard Worker 675*333d2b36SAndroid Build Coastguard Worker for _, output := range outputs { 676*333d2b36SAndroid Build Coastguard Worker if p := get(output); p != nil { 677*333d2b36SAndroid Build Coastguard Worker paths = append(paths, p) 678*333d2b36SAndroid Build Coastguard Worker } 679*333d2b36SAndroid Build Coastguard Worker } 680*333d2b36SAndroid Build Coastguard Worker 681*333d2b36SAndroid Build Coastguard Worker lintZip(ctx, paths, outputPath, nil) 682*333d2b36SAndroid Build Coastguard Worker } 683*333d2b36SAndroid Build Coastguard Worker 684*333d2b36SAndroid Build Coastguard Worker l.htmlZip = android.PathForOutput(ctx, "lint-report-html.zip") 685*333d2b36SAndroid Build Coastguard Worker zip(l.htmlZip, func(l *LintInfo) android.Path { return l.HTML }) 686*333d2b36SAndroid Build Coastguard Worker 687*333d2b36SAndroid Build Coastguard Worker l.textZip = android.PathForOutput(ctx, "lint-report-text.zip") 688*333d2b36SAndroid Build Coastguard Worker zip(l.textZip, func(l *LintInfo) android.Path { return l.Text }) 689*333d2b36SAndroid Build Coastguard Worker 690*333d2b36SAndroid Build Coastguard Worker l.xmlZip = android.PathForOutput(ctx, "lint-report-xml.zip") 691*333d2b36SAndroid Build Coastguard Worker zip(l.xmlZip, func(l *LintInfo) android.Path { return l.XML }) 692*333d2b36SAndroid Build Coastguard Worker 693*333d2b36SAndroid Build Coastguard Worker l.referenceBaselineZip = android.PathForOutput(ctx, "lint-report-reference-baselines.zip") 694*333d2b36SAndroid Build Coastguard Worker zip(l.referenceBaselineZip, func(l *LintInfo) android.Path { return l.ReferenceBaseline }) 695*333d2b36SAndroid Build Coastguard Worker 696*333d2b36SAndroid Build Coastguard Worker ctx.Phony("lint-check", l.htmlZip, l.textZip, l.xmlZip, l.referenceBaselineZip) 697*333d2b36SAndroid Build Coastguard Worker} 698*333d2b36SAndroid Build Coastguard Worker 699*333d2b36SAndroid Build Coastguard Workerfunc (l *lintSingleton) MakeVars(ctx android.MakeVarsContext) { 700*333d2b36SAndroid Build Coastguard Worker if !ctx.Config().UnbundledBuild() { 701*333d2b36SAndroid Build Coastguard Worker ctx.DistForGoal("lint-check", l.htmlZip, l.textZip, l.xmlZip, l.referenceBaselineZip) 702*333d2b36SAndroid Build Coastguard Worker } 703*333d2b36SAndroid Build Coastguard Worker} 704*333d2b36SAndroid Build Coastguard Worker 705*333d2b36SAndroid Build Coastguard Workervar _ android.SingletonMakeVarsProvider = (*lintSingleton)(nil) 706*333d2b36SAndroid Build Coastguard Worker 707*333d2b36SAndroid Build Coastguard Workerfunc init() { 708*333d2b36SAndroid Build Coastguard Worker android.RegisterParallelSingletonType("lint", 709*333d2b36SAndroid Build Coastguard Worker func() android.Singleton { return &lintSingleton{} }) 710*333d2b36SAndroid Build Coastguard Worker} 711*333d2b36SAndroid Build Coastguard Worker 712*333d2b36SAndroid Build Coastguard Workerfunc lintZip(ctx android.BuilderContext, paths android.Paths, outputPath android.WritablePath, validations android.Paths) { 713*333d2b36SAndroid Build Coastguard Worker paths = android.SortedUniquePaths(android.CopyOfPaths(paths)) 714*333d2b36SAndroid Build Coastguard Worker 715*333d2b36SAndroid Build Coastguard Worker sort.Slice(paths, func(i, j int) bool { 716*333d2b36SAndroid Build Coastguard Worker return paths[i].String() < paths[j].String() 717*333d2b36SAndroid Build Coastguard Worker }) 718*333d2b36SAndroid Build Coastguard Worker 719*333d2b36SAndroid Build Coastguard Worker rule := android.NewRuleBuilder(pctx, ctx) 720*333d2b36SAndroid Build Coastguard Worker 721*333d2b36SAndroid Build Coastguard Worker rule.Command().BuiltTool("soong_zip"). 722*333d2b36SAndroid Build Coastguard Worker FlagWithOutput("-o ", outputPath). 723*333d2b36SAndroid Build Coastguard Worker FlagWithArg("-C ", android.PathForIntermediates(ctx).String()). 724*333d2b36SAndroid Build Coastguard Worker FlagWithRspFileInputList("-r ", outputPath.ReplaceExtension(ctx, "rsp"), paths). 725*333d2b36SAndroid Build Coastguard Worker Validations(validations) 726*333d2b36SAndroid Build Coastguard Worker 727*333d2b36SAndroid Build Coastguard Worker rule.Build(outputPath.Base(), outputPath.Base()) 728*333d2b36SAndroid Build Coastguard Worker} 729