1*333d2b36SAndroid Build Coastguard Worker// Copyright 2016 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 cc 16*333d2b36SAndroid Build Coastguard Worker 17*333d2b36SAndroid Build Coastguard Workerimport ( 18*333d2b36SAndroid Build Coastguard Worker "fmt" 19*333d2b36SAndroid Build Coastguard Worker "path/filepath" 20*333d2b36SAndroid Build Coastguard Worker "regexp" 21*333d2b36SAndroid Build Coastguard Worker "strings" 22*333d2b36SAndroid Build Coastguard Worker 23*333d2b36SAndroid Build Coastguard Worker "github.com/google/blueprint/proptools" 24*333d2b36SAndroid Build Coastguard Worker 25*333d2b36SAndroid Build Coastguard Worker "android/soong/android" 26*333d2b36SAndroid Build Coastguard Worker "android/soong/cc/config" 27*333d2b36SAndroid Build Coastguard Worker) 28*333d2b36SAndroid Build Coastguard Worker 29*333d2b36SAndroid Build Coastguard Workertype TidyProperties struct { 30*333d2b36SAndroid Build Coastguard Worker // whether to run clang-tidy over C-like sources. 31*333d2b36SAndroid Build Coastguard Worker Tidy *bool 32*333d2b36SAndroid Build Coastguard Worker 33*333d2b36SAndroid Build Coastguard Worker // Extra flags to pass to clang-tidy 34*333d2b36SAndroid Build Coastguard Worker Tidy_flags []string 35*333d2b36SAndroid Build Coastguard Worker 36*333d2b36SAndroid Build Coastguard Worker // Extra checks to enable or disable in clang-tidy 37*333d2b36SAndroid Build Coastguard Worker Tidy_checks []string 38*333d2b36SAndroid Build Coastguard Worker 39*333d2b36SAndroid Build Coastguard Worker // Checks that should be treated as errors. 40*333d2b36SAndroid Build Coastguard Worker Tidy_checks_as_errors []string 41*333d2b36SAndroid Build Coastguard Worker} 42*333d2b36SAndroid Build Coastguard Worker 43*333d2b36SAndroid Build Coastguard Workertype tidyFeature struct { 44*333d2b36SAndroid Build Coastguard Worker Properties TidyProperties 45*333d2b36SAndroid Build Coastguard Worker} 46*333d2b36SAndroid Build Coastguard Worker 47*333d2b36SAndroid Build Coastguard Workervar quotedFlagRegexp, _ = regexp.Compile(`^-?-[^=]+=('|").*('|")$`) 48*333d2b36SAndroid Build Coastguard Worker 49*333d2b36SAndroid Build Coastguard Worker// When passing flag -name=value, if user add quotes around 'value', 50*333d2b36SAndroid Build Coastguard Worker// the quotation marks will be preserved by NinjaAndShellEscapeList 51*333d2b36SAndroid Build Coastguard Worker// and the 'value' string with quotes won't work like the intended value. 52*333d2b36SAndroid Build Coastguard Worker// So here we report an error if -*='*' is found. 53*333d2b36SAndroid Build Coastguard Workerfunc checkNinjaAndShellEscapeList(ctx ModuleContext, prop string, slice []string) []string { 54*333d2b36SAndroid Build Coastguard Worker for _, s := range slice { 55*333d2b36SAndroid Build Coastguard Worker if quotedFlagRegexp.MatchString(s) { 56*333d2b36SAndroid Build Coastguard Worker ctx.PropertyErrorf(prop, "Extra quotes in: %s", s) 57*333d2b36SAndroid Build Coastguard Worker } 58*333d2b36SAndroid Build Coastguard Worker } 59*333d2b36SAndroid Build Coastguard Worker return proptools.NinjaAndShellEscapeList(slice) 60*333d2b36SAndroid Build Coastguard Worker} 61*333d2b36SAndroid Build Coastguard Worker 62*333d2b36SAndroid Build Coastguard Workerfunc (tidy *tidyFeature) props() []interface{} { 63*333d2b36SAndroid Build Coastguard Worker return []interface{}{&tidy.Properties} 64*333d2b36SAndroid Build Coastguard Worker} 65*333d2b36SAndroid Build Coastguard Worker 66*333d2b36SAndroid Build Coastguard Worker// Set this const to true when all -warnings-as-errors in tidy_flags 67*333d2b36SAndroid Build Coastguard Worker// are replaced with tidy_checks_as_errors. 68*333d2b36SAndroid Build Coastguard Worker// Then, that old style usage will be obsolete and an error. 69*333d2b36SAndroid Build Coastguard Workerconst NoWarningsAsErrorsInTidyFlags = true 70*333d2b36SAndroid Build Coastguard Worker 71*333d2b36SAndroid Build Coastguard Workerfunc (tidy *tidyFeature) flags(ctx ModuleContext, flags Flags) Flags { 72*333d2b36SAndroid Build Coastguard Worker CheckBadTidyFlags(ctx, "tidy_flags", tidy.Properties.Tidy_flags) 73*333d2b36SAndroid Build Coastguard Worker CheckBadTidyChecks(ctx, "tidy_checks", tidy.Properties.Tidy_checks) 74*333d2b36SAndroid Build Coastguard Worker 75*333d2b36SAndroid Build Coastguard Worker // Check if tidy is explicitly disabled for this module 76*333d2b36SAndroid Build Coastguard Worker if tidy.Properties.Tidy != nil && !*tidy.Properties.Tidy { 77*333d2b36SAndroid Build Coastguard Worker return flags 78*333d2b36SAndroid Build Coastguard Worker } 79*333d2b36SAndroid Build Coastguard Worker // Some projects like external/* and vendor/* have clang-tidy disabled by default, 80*333d2b36SAndroid Build Coastguard Worker // unless they are enabled explicitly with the "tidy:true" property or 81*333d2b36SAndroid Build Coastguard Worker // when TIDY_EXTERNAL_VENDOR is set to true. 82*333d2b36SAndroid Build Coastguard Worker if !proptools.Bool(tidy.Properties.Tidy) && 83*333d2b36SAndroid Build Coastguard Worker config.NoClangTidyForDir( 84*333d2b36SAndroid Build Coastguard Worker ctx.Config().IsEnvTrue("TIDY_EXTERNAL_VENDOR"), 85*333d2b36SAndroid Build Coastguard Worker ctx.ModuleDir()) { 86*333d2b36SAndroid Build Coastguard Worker return flags 87*333d2b36SAndroid Build Coastguard Worker } 88*333d2b36SAndroid Build Coastguard Worker // If not explicitly disabled, set flags.Tidy to generate .tidy rules. 89*333d2b36SAndroid Build Coastguard Worker // Note that libraries and binaries will depend on .tidy files ONLY if 90*333d2b36SAndroid Build Coastguard Worker // the global WITH_TIDY or module 'tidy' property is true. 91*333d2b36SAndroid Build Coastguard Worker flags.Tidy = true 92*333d2b36SAndroid Build Coastguard Worker 93*333d2b36SAndroid Build Coastguard Worker // If explicitly enabled, by global WITH_TIDY or local tidy:true property, 94*333d2b36SAndroid Build Coastguard Worker // set flags.NeedTidyFiles to make this module depend on .tidy files. 95*333d2b36SAndroid Build Coastguard Worker // Note that locally set tidy:true is ignored if ALLOW_LOCAL_TIDY_TRUE is not set to true. 96*333d2b36SAndroid Build Coastguard Worker if ctx.Config().IsEnvTrue("WITH_TIDY") || (ctx.Config().IsEnvTrue("ALLOW_LOCAL_TIDY_TRUE") && Bool(tidy.Properties.Tidy)) { 97*333d2b36SAndroid Build Coastguard Worker flags.NeedTidyFiles = true 98*333d2b36SAndroid Build Coastguard Worker } 99*333d2b36SAndroid Build Coastguard Worker 100*333d2b36SAndroid Build Coastguard Worker // Add global WITH_TIDY_FLAGS and local tidy_flags. 101*333d2b36SAndroid Build Coastguard Worker withTidyFlags := ctx.Config().Getenv("WITH_TIDY_FLAGS") 102*333d2b36SAndroid Build Coastguard Worker if len(withTidyFlags) > 0 { 103*333d2b36SAndroid Build Coastguard Worker flags.TidyFlags = append(flags.TidyFlags, withTidyFlags) 104*333d2b36SAndroid Build Coastguard Worker } 105*333d2b36SAndroid Build Coastguard Worker esc := checkNinjaAndShellEscapeList 106*333d2b36SAndroid Build Coastguard Worker flags.TidyFlags = append(flags.TidyFlags, esc(ctx, "tidy_flags", tidy.Properties.Tidy_flags)...) 107*333d2b36SAndroid Build Coastguard Worker // If TidyFlags does not contain -header-filter, add default header filter. 108*333d2b36SAndroid Build Coastguard Worker // Find the substring because the flag could also appear as --header-filter=... 109*333d2b36SAndroid Build Coastguard Worker // and with or without single or double quotes. 110*333d2b36SAndroid Build Coastguard Worker if !android.SubstringInList(flags.TidyFlags, "-header-filter=") { 111*333d2b36SAndroid Build Coastguard Worker defaultDirs := ctx.Config().Getenv("DEFAULT_TIDY_HEADER_DIRS") 112*333d2b36SAndroid Build Coastguard Worker headerFilter := "-header-filter=" 113*333d2b36SAndroid Build Coastguard Worker // Default header filter should include only the module directory, 114*333d2b36SAndroid Build Coastguard Worker // not the out/soong/.../ModuleDir/... 115*333d2b36SAndroid Build Coastguard Worker // Otherwise, there will be too many warnings from generated files in out/... 116*333d2b36SAndroid Build Coastguard Worker // If a module wants to see warnings in the generated source files, 117*333d2b36SAndroid Build Coastguard Worker // it should specify its own -header-filter flag. 118*333d2b36SAndroid Build Coastguard Worker if defaultDirs == "" { 119*333d2b36SAndroid Build Coastguard Worker headerFilter += "^" + ctx.ModuleDir() + "/" 120*333d2b36SAndroid Build Coastguard Worker } else { 121*333d2b36SAndroid Build Coastguard Worker headerFilter += "\"(^" + ctx.ModuleDir() + "/|" + defaultDirs + ")\"" 122*333d2b36SAndroid Build Coastguard Worker } 123*333d2b36SAndroid Build Coastguard Worker flags.TidyFlags = append(flags.TidyFlags, headerFilter) 124*333d2b36SAndroid Build Coastguard Worker } 125*333d2b36SAndroid Build Coastguard Worker // Work around RBE bug in parsing clang-tidy flags, replace "--flag" with "-flag". 126*333d2b36SAndroid Build Coastguard Worker // Some C/C++ modules added local tidy flags like --header-filter= and --extra-arg-before=. 127*333d2b36SAndroid Build Coastguard Worker doubleDash := regexp.MustCompile("^('?)--(.*)$") 128*333d2b36SAndroid Build Coastguard Worker for i, s := range flags.TidyFlags { 129*333d2b36SAndroid Build Coastguard Worker flags.TidyFlags[i] = doubleDash.ReplaceAllString(s, "$1-$2") 130*333d2b36SAndroid Build Coastguard Worker } 131*333d2b36SAndroid Build Coastguard Worker 132*333d2b36SAndroid Build Coastguard Worker // If clang-tidy is not enabled globally, add the -quiet flag. 133*333d2b36SAndroid Build Coastguard Worker if !ctx.Config().ClangTidy() { 134*333d2b36SAndroid Build Coastguard Worker flags.TidyFlags = append(flags.TidyFlags, "-quiet") 135*333d2b36SAndroid Build Coastguard Worker flags.TidyFlags = append(flags.TidyFlags, "-extra-arg-before=-fno-caret-diagnostics") 136*333d2b36SAndroid Build Coastguard Worker } 137*333d2b36SAndroid Build Coastguard Worker 138*333d2b36SAndroid Build Coastguard Worker for _, f := range config.TidyExtraArgFlags() { 139*333d2b36SAndroid Build Coastguard Worker flags.TidyFlags = append(flags.TidyFlags, "-extra-arg-before="+f) 140*333d2b36SAndroid Build Coastguard Worker } 141*333d2b36SAndroid Build Coastguard Worker 142*333d2b36SAndroid Build Coastguard Worker tidyChecks := "-checks=" 143*333d2b36SAndroid Build Coastguard Worker if checks := ctx.Config().TidyChecks(); len(checks) > 0 { 144*333d2b36SAndroid Build Coastguard Worker tidyChecks += checks 145*333d2b36SAndroid Build Coastguard Worker } else { 146*333d2b36SAndroid Build Coastguard Worker tidyChecks += config.TidyChecksForDir(ctx.ModuleDir()) 147*333d2b36SAndroid Build Coastguard Worker } 148*333d2b36SAndroid Build Coastguard Worker if len(tidy.Properties.Tidy_checks) > 0 { 149*333d2b36SAndroid Build Coastguard Worker // If Tidy_checks contains "-*", ignore all checks before "-*". 150*333d2b36SAndroid Build Coastguard Worker localChecks := tidy.Properties.Tidy_checks 151*333d2b36SAndroid Build Coastguard Worker ignoreGlobalChecks := false 152*333d2b36SAndroid Build Coastguard Worker for n, check := range tidy.Properties.Tidy_checks { 153*333d2b36SAndroid Build Coastguard Worker if check == "-*" { 154*333d2b36SAndroid Build Coastguard Worker ignoreGlobalChecks = true 155*333d2b36SAndroid Build Coastguard Worker localChecks = tidy.Properties.Tidy_checks[n:] 156*333d2b36SAndroid Build Coastguard Worker } 157*333d2b36SAndroid Build Coastguard Worker } 158*333d2b36SAndroid Build Coastguard Worker if ignoreGlobalChecks { 159*333d2b36SAndroid Build Coastguard Worker tidyChecks = "-checks=" + strings.Join(esc(ctx, "tidy_checks", 160*333d2b36SAndroid Build Coastguard Worker config.ClangRewriteTidyChecks(localChecks)), ",") 161*333d2b36SAndroid Build Coastguard Worker } else { 162*333d2b36SAndroid Build Coastguard Worker tidyChecks = tidyChecks + "," + strings.Join(esc(ctx, "tidy_checks", 163*333d2b36SAndroid Build Coastguard Worker config.ClangRewriteTidyChecks(localChecks)), ",") 164*333d2b36SAndroid Build Coastguard Worker } 165*333d2b36SAndroid Build Coastguard Worker } 166*333d2b36SAndroid Build Coastguard Worker tidyChecks = tidyChecks + config.TidyGlobalNoChecks() 167*333d2b36SAndroid Build Coastguard Worker if ctx.Windows() { 168*333d2b36SAndroid Build Coastguard Worker // https://b.corp.google.com/issues/120614316 169*333d2b36SAndroid Build Coastguard Worker // mingw32 has cert-dcl16-c warning in NO_ERROR, 170*333d2b36SAndroid Build Coastguard Worker // which is used in many Android files. 171*333d2b36SAndroid Build Coastguard Worker tidyChecks += ",-cert-dcl16-c" 172*333d2b36SAndroid Build Coastguard Worker } 173*333d2b36SAndroid Build Coastguard Worker 174*333d2b36SAndroid Build Coastguard Worker flags.TidyFlags = append(flags.TidyFlags, tidyChecks) 175*333d2b36SAndroid Build Coastguard Worker 176*333d2b36SAndroid Build Coastguard Worker // Embedding -warnings-as-errors in tidy_flags is error-prone. 177*333d2b36SAndroid Build Coastguard Worker // It should be replaced with the tidy_checks_as_errors list. 178*333d2b36SAndroid Build Coastguard Worker for i, s := range flags.TidyFlags { 179*333d2b36SAndroid Build Coastguard Worker if strings.Contains(s, "-warnings-as-errors=") { 180*333d2b36SAndroid Build Coastguard Worker if NoWarningsAsErrorsInTidyFlags { 181*333d2b36SAndroid Build Coastguard Worker ctx.PropertyErrorf("tidy_flags", "should not contain "+s+"; use tidy_checks_as_errors instead.") 182*333d2b36SAndroid Build Coastguard Worker } else { 183*333d2b36SAndroid Build Coastguard Worker fmt.Printf("%s: warning: module %s's tidy_flags should not contain %s, which is replaced with -warnings-as-errors=-*; use tidy_checks_as_errors for your own as-error warnings instead.\n", 184*333d2b36SAndroid Build Coastguard Worker ctx.BlueprintsFile(), ctx.ModuleName(), s) 185*333d2b36SAndroid Build Coastguard Worker flags.TidyFlags[i] = "-warnings-as-errors=-*" 186*333d2b36SAndroid Build Coastguard Worker } 187*333d2b36SAndroid Build Coastguard Worker break // there is at most one -warnings-as-errors 188*333d2b36SAndroid Build Coastguard Worker } 189*333d2b36SAndroid Build Coastguard Worker } 190*333d2b36SAndroid Build Coastguard Worker // Default clang-tidy flags does not contain -warning-as-errors. 191*333d2b36SAndroid Build Coastguard Worker // If a module has tidy_checks_as_errors, add the list to -warnings-as-errors 192*333d2b36SAndroid Build Coastguard Worker // and then append the TidyGlobalNoErrorChecks. 193*333d2b36SAndroid Build Coastguard Worker if len(tidy.Properties.Tidy_checks_as_errors) > 0 { 194*333d2b36SAndroid Build Coastguard Worker tidyChecksAsErrors := "-warnings-as-errors=" + 195*333d2b36SAndroid Build Coastguard Worker strings.Join(esc(ctx, "tidy_checks_as_errors", tidy.Properties.Tidy_checks_as_errors), ",") + 196*333d2b36SAndroid Build Coastguard Worker config.TidyGlobalNoErrorChecks() 197*333d2b36SAndroid Build Coastguard Worker flags.TidyFlags = append(flags.TidyFlags, tidyChecksAsErrors) 198*333d2b36SAndroid Build Coastguard Worker } 199*333d2b36SAndroid Build Coastguard Worker return flags 200*333d2b36SAndroid Build Coastguard Worker} 201*333d2b36SAndroid Build Coastguard Worker 202*333d2b36SAndroid Build Coastguard Workerfunc init() { 203*333d2b36SAndroid Build Coastguard Worker android.RegisterParallelSingletonType("tidy_phony_targets", TidyPhonySingleton) 204*333d2b36SAndroid Build Coastguard Worker} 205*333d2b36SAndroid Build Coastguard Worker 206*333d2b36SAndroid Build Coastguard Worker// This TidyPhonySingleton generates both tidy-* and obj-* phony targets for C/C++ files. 207*333d2b36SAndroid Build Coastguard Workerfunc TidyPhonySingleton() android.Singleton { 208*333d2b36SAndroid Build Coastguard Worker return &tidyPhonySingleton{} 209*333d2b36SAndroid Build Coastguard Worker} 210*333d2b36SAndroid Build Coastguard Worker 211*333d2b36SAndroid Build Coastguard Workertype tidyPhonySingleton struct{} 212*333d2b36SAndroid Build Coastguard Worker 213*333d2b36SAndroid Build Coastguard Worker// Given a final module, add its tidy/obj phony targets to tidy/objModulesInDirGroup. 214*333d2b36SAndroid Build Coastguard Workerfunc collectTidyObjModuleTargets(ctx android.SingletonContext, module android.Module, 215*333d2b36SAndroid Build Coastguard Worker tidyModulesInDirGroup, objModulesInDirGroup map[string]map[string]android.Paths) { 216*333d2b36SAndroid Build Coastguard Worker allObjFileGroups := make(map[string]android.Paths) // variant group name => obj file Paths 217*333d2b36SAndroid Build Coastguard Worker allTidyFileGroups := make(map[string]android.Paths) // variant group name => tidy file Paths 218*333d2b36SAndroid Build Coastguard Worker subsetObjFileGroups := make(map[string]android.Paths) // subset group name => obj file Paths 219*333d2b36SAndroid Build Coastguard Worker subsetTidyFileGroups := make(map[string]android.Paths) // subset group name => tidy file Paths 220*333d2b36SAndroid Build Coastguard Worker 221*333d2b36SAndroid Build Coastguard Worker // (1) Collect all obj/tidy files into OS-specific groups. 222*333d2b36SAndroid Build Coastguard Worker ctx.VisitAllModuleVariantProxies(module, func(variant android.ModuleProxy) { 223*333d2b36SAndroid Build Coastguard Worker osName := android.OtherModuleProviderOrDefault(ctx, variant, android.CommonModuleInfoKey).CompileTarget.Os.Name 224*333d2b36SAndroid Build Coastguard Worker info := android.OtherModuleProviderOrDefault(ctx, variant, CcObjectInfoProvider) 225*333d2b36SAndroid Build Coastguard Worker addToOSGroup(osName, info.objFiles, allObjFileGroups, subsetObjFileGroups) 226*333d2b36SAndroid Build Coastguard Worker addToOSGroup(osName, info.tidyFiles, allTidyFileGroups, subsetTidyFileGroups) 227*333d2b36SAndroid Build Coastguard Worker }) 228*333d2b36SAndroid Build Coastguard Worker 229*333d2b36SAndroid Build Coastguard Worker // (2) Add an all-OS group, with "" or "subset" name, to include all os-specific phony targets. 230*333d2b36SAndroid Build Coastguard Worker addAllOSGroup(ctx, module, allObjFileGroups, "", "obj") 231*333d2b36SAndroid Build Coastguard Worker addAllOSGroup(ctx, module, allTidyFileGroups, "", "tidy") 232*333d2b36SAndroid Build Coastguard Worker addAllOSGroup(ctx, module, subsetObjFileGroups, "subset", "obj") 233*333d2b36SAndroid Build Coastguard Worker addAllOSGroup(ctx, module, subsetTidyFileGroups, "subset", "tidy") 234*333d2b36SAndroid Build Coastguard Worker 235*333d2b36SAndroid Build Coastguard Worker tidyTargetGroups := make(map[string]android.Path) 236*333d2b36SAndroid Build Coastguard Worker objTargetGroups := make(map[string]android.Path) 237*333d2b36SAndroid Build Coastguard Worker genObjTidyPhonyTargets(ctx, module, "obj", allObjFileGroups, objTargetGroups) 238*333d2b36SAndroid Build Coastguard Worker genObjTidyPhonyTargets(ctx, module, "obj", subsetObjFileGroups, objTargetGroups) 239*333d2b36SAndroid Build Coastguard Worker genObjTidyPhonyTargets(ctx, module, "tidy", allTidyFileGroups, tidyTargetGroups) 240*333d2b36SAndroid Build Coastguard Worker genObjTidyPhonyTargets(ctx, module, "tidy", subsetTidyFileGroups, tidyTargetGroups) 241*333d2b36SAndroid Build Coastguard Worker 242*333d2b36SAndroid Build Coastguard Worker moduleDir := ctx.ModuleDir(module) 243*333d2b36SAndroid Build Coastguard Worker appendToModulesInDirGroup(tidyTargetGroups, moduleDir, tidyModulesInDirGroup) 244*333d2b36SAndroid Build Coastguard Worker appendToModulesInDirGroup(objTargetGroups, moduleDir, objModulesInDirGroup) 245*333d2b36SAndroid Build Coastguard Worker} 246*333d2b36SAndroid Build Coastguard Worker 247*333d2b36SAndroid Build Coastguard Workerfunc (m *tidyPhonySingleton) GenerateBuildActions(ctx android.SingletonContext) { 248*333d2b36SAndroid Build Coastguard Worker // For tidy-* directory phony targets, there are different variant groups. 249*333d2b36SAndroid Build Coastguard Worker // tidyModulesInDirGroup[G][D] is for group G, directory D, with Paths 250*333d2b36SAndroid Build Coastguard Worker // of all phony targets to be included into direct dependents of tidy-D_G. 251*333d2b36SAndroid Build Coastguard Worker tidyModulesInDirGroup := make(map[string]map[string]android.Paths) 252*333d2b36SAndroid Build Coastguard Worker // Also for obj-* directory phony targets. 253*333d2b36SAndroid Build Coastguard Worker objModulesInDirGroup := make(map[string]map[string]android.Paths) 254*333d2b36SAndroid Build Coastguard Worker 255*333d2b36SAndroid Build Coastguard Worker // Collect tidy/obj targets from the 'final' modules. 256*333d2b36SAndroid Build Coastguard Worker ctx.VisitAllModules(func(module android.Module) { 257*333d2b36SAndroid Build Coastguard Worker if ctx.IsFinalModule(module) { 258*333d2b36SAndroid Build Coastguard Worker collectTidyObjModuleTargets(ctx, module, tidyModulesInDirGroup, objModulesInDirGroup) 259*333d2b36SAndroid Build Coastguard Worker } 260*333d2b36SAndroid Build Coastguard Worker }) 261*333d2b36SAndroid Build Coastguard Worker 262*333d2b36SAndroid Build Coastguard Worker suffix := "" 263*333d2b36SAndroid Build Coastguard Worker if ctx.Config().KatiEnabled() { 264*333d2b36SAndroid Build Coastguard Worker suffix = "-soong" 265*333d2b36SAndroid Build Coastguard Worker } 266*333d2b36SAndroid Build Coastguard Worker generateObjTidyPhonyTargets(ctx, suffix, "obj", objModulesInDirGroup) 267*333d2b36SAndroid Build Coastguard Worker generateObjTidyPhonyTargets(ctx, suffix, "tidy", tidyModulesInDirGroup) 268*333d2b36SAndroid Build Coastguard Worker} 269*333d2b36SAndroid Build Coastguard Worker 270*333d2b36SAndroid Build Coastguard Worker// The name for an obj/tidy module variant group phony target is Name_group-obj/tidy, 271*333d2b36SAndroid Build Coastguard Workerfunc objTidyModuleGroupName(module android.Module, group string, suffix string) string { 272*333d2b36SAndroid Build Coastguard Worker if group == "" { 273*333d2b36SAndroid Build Coastguard Worker return module.Name() + "-" + suffix 274*333d2b36SAndroid Build Coastguard Worker } 275*333d2b36SAndroid Build Coastguard Worker return module.Name() + "_" + group + "-" + suffix 276*333d2b36SAndroid Build Coastguard Worker} 277*333d2b36SAndroid Build Coastguard Worker 278*333d2b36SAndroid Build Coastguard Worker// Generate obj-* or tidy-* phony targets. 279*333d2b36SAndroid Build Coastguard Workerfunc generateObjTidyPhonyTargets(ctx android.SingletonContext, suffix string, prefix string, objTidyModulesInDirGroup map[string]map[string]android.Paths) { 280*333d2b36SAndroid Build Coastguard Worker // For each variant group, create a <prefix>-<directory>_group target that 281*333d2b36SAndroid Build Coastguard Worker // depends on all subdirectories and modules in the directory. 282*333d2b36SAndroid Build Coastguard Worker for group, modulesInDir := range objTidyModulesInDirGroup { 283*333d2b36SAndroid Build Coastguard Worker groupSuffix := "" 284*333d2b36SAndroid Build Coastguard Worker if group != "" { 285*333d2b36SAndroid Build Coastguard Worker groupSuffix = "_" + group 286*333d2b36SAndroid Build Coastguard Worker } 287*333d2b36SAndroid Build Coastguard Worker mmTarget := func(dir string) string { 288*333d2b36SAndroid Build Coastguard Worker return prefix + "-" + strings.Replace(filepath.Clean(dir), "/", "-", -1) + groupSuffix 289*333d2b36SAndroid Build Coastguard Worker } 290*333d2b36SAndroid Build Coastguard Worker dirs, topDirs := android.AddAncestors(ctx, modulesInDir, mmTarget) 291*333d2b36SAndroid Build Coastguard Worker // Create a <prefix>-soong_group target that depends on all <prefix>-dir_group of top level dirs. 292*333d2b36SAndroid Build Coastguard Worker var topDirPaths android.Paths 293*333d2b36SAndroid Build Coastguard Worker for _, dir := range topDirs { 294*333d2b36SAndroid Build Coastguard Worker topDirPaths = append(topDirPaths, android.PathForPhony(ctx, mmTarget(dir))) 295*333d2b36SAndroid Build Coastguard Worker } 296*333d2b36SAndroid Build Coastguard Worker ctx.Phony(prefix+suffix+groupSuffix, topDirPaths...) 297*333d2b36SAndroid Build Coastguard Worker // Create a <prefix>-dir_group target that depends on all targets in modulesInDir[dir] 298*333d2b36SAndroid Build Coastguard Worker for _, dir := range dirs { 299*333d2b36SAndroid Build Coastguard Worker if dir != "." && dir != "" { 300*333d2b36SAndroid Build Coastguard Worker ctx.Phony(mmTarget(dir), modulesInDir[dir]...) 301*333d2b36SAndroid Build Coastguard Worker } 302*333d2b36SAndroid Build Coastguard Worker } 303*333d2b36SAndroid Build Coastguard Worker } 304*333d2b36SAndroid Build Coastguard Worker} 305*333d2b36SAndroid Build Coastguard Worker 306*333d2b36SAndroid Build Coastguard Worker// Append (obj|tidy)TargetGroups[group] into (obj|tidy)ModulesInDirGroups[group][moduleDir]. 307*333d2b36SAndroid Build Coastguard Workerfunc appendToModulesInDirGroup(targetGroups map[string]android.Path, moduleDir string, modulesInDirGroup map[string]map[string]android.Paths) { 308*333d2b36SAndroid Build Coastguard Worker for group, phonyPath := range targetGroups { 309*333d2b36SAndroid Build Coastguard Worker if _, found := modulesInDirGroup[group]; !found { 310*333d2b36SAndroid Build Coastguard Worker modulesInDirGroup[group] = make(map[string]android.Paths) 311*333d2b36SAndroid Build Coastguard Worker } 312*333d2b36SAndroid Build Coastguard Worker modulesInDirGroup[group][moduleDir] = append(modulesInDirGroup[group][moduleDir], phonyPath) 313*333d2b36SAndroid Build Coastguard Worker } 314*333d2b36SAndroid Build Coastguard Worker} 315*333d2b36SAndroid Build Coastguard Worker 316*333d2b36SAndroid Build Coastguard Worker// Add given files to the OS group and subset group. 317*333d2b36SAndroid Build Coastguard Workerfunc addToOSGroup(osName string, files android.Paths, allGroups, subsetGroups map[string]android.Paths) { 318*333d2b36SAndroid Build Coastguard Worker if len(files) > 0 { 319*333d2b36SAndroid Build Coastguard Worker subsetName := osName + "_subset" 320*333d2b36SAndroid Build Coastguard Worker allGroups[osName] = append(allGroups[osName], files...) 321*333d2b36SAndroid Build Coastguard Worker // Now include only the first variant in the subsetGroups. 322*333d2b36SAndroid Build Coastguard Worker // If clang and clang-tidy get faster, we might include more variants. 323*333d2b36SAndroid Build Coastguard Worker if _, found := subsetGroups[subsetName]; !found { 324*333d2b36SAndroid Build Coastguard Worker subsetGroups[subsetName] = files 325*333d2b36SAndroid Build Coastguard Worker } 326*333d2b36SAndroid Build Coastguard Worker } 327*333d2b36SAndroid Build Coastguard Worker} 328*333d2b36SAndroid Build Coastguard Worker 329*333d2b36SAndroid Build Coastguard Worker// Add an all-OS group, with groupName, to include all os-specific phony targets. 330*333d2b36SAndroid Build Coastguard Workerfunc addAllOSGroup(ctx android.SingletonContext, module android.Module, phonyTargetGroups map[string]android.Paths, groupName string, objTidyName string) { 331*333d2b36SAndroid Build Coastguard Worker if len(phonyTargetGroups) > 0 { 332*333d2b36SAndroid Build Coastguard Worker var targets android.Paths 333*333d2b36SAndroid Build Coastguard Worker for group, _ := range phonyTargetGroups { 334*333d2b36SAndroid Build Coastguard Worker targets = append(targets, android.PathForPhony(ctx, objTidyModuleGroupName(module, group, objTidyName))) 335*333d2b36SAndroid Build Coastguard Worker } 336*333d2b36SAndroid Build Coastguard Worker phonyTargetGroups[groupName] = targets 337*333d2b36SAndroid Build Coastguard Worker } 338*333d2b36SAndroid Build Coastguard Worker} 339*333d2b36SAndroid Build Coastguard Worker 340*333d2b36SAndroid Build Coastguard Worker// Create one phony targets for each group and add them to the targetGroups. 341*333d2b36SAndroid Build Coastguard Workerfunc genObjTidyPhonyTargets(ctx android.SingletonContext, module android.Module, objTidyName string, fileGroups map[string]android.Paths, targetGroups map[string]android.Path) { 342*333d2b36SAndroid Build Coastguard Worker for group, files := range fileGroups { 343*333d2b36SAndroid Build Coastguard Worker groupName := objTidyModuleGroupName(module, group, objTidyName) 344*333d2b36SAndroid Build Coastguard Worker ctx.Phony(groupName, files...) 345*333d2b36SAndroid Build Coastguard Worker targetGroups[group] = android.PathForPhony(ctx, groupName) 346*333d2b36SAndroid Build Coastguard Worker } 347*333d2b36SAndroid Build Coastguard Worker} 348