Generate tidy-* rules unless tidy is disabled

* make tidy-soong_subset, or make tidy-<any_directory>,
  should trigger the same clang-tidy compilations
  with or without global WITH_TIDY=1.
* Normal make should not trigger clang-tidy compilations
  unless global WITH_TIDY=1 or a module has set tidy:true.

Bug: 213918926
Test: NINJA_ARGS="-n" make tidy-soong_subset
Test: NINJA_ARGS="-n" make <some-library>
Change-Id: Iafffd3894abe137c9584c2c01830898422f9a677
diff --git a/cc/binary.go b/cc/binary.go
index b59e762..ee3de3f 100644
--- a/cc/binary.go
+++ b/cc/binary.go
@@ -427,7 +427,7 @@
 		linkerDeps = append(linkerDeps, ndkSharedLibDeps(ctx)...)
 	}
 
-	validations = append(validations, objs.tidyFiles...)
+	validations = append(validations, objs.tidyDepFiles...)
 	linkerDeps = append(linkerDeps, flags.LdFlagsDeps...)
 
 	// Register link action.
diff --git a/cc/builder.go b/cc/builder.go
index fa7f7a3..512f838 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -387,10 +387,11 @@
 	toolchain     config.Toolchain
 
 	// True if these extra features are enabled.
-	tidy         bool
-	gcovCoverage bool
-	sAbiDump     bool
-	emitXrefs    bool
+	tidy          bool
+	needTidyFiles bool
+	gcovCoverage  bool
+	sAbiDump      bool
+	emitXrefs     bool
 
 	assemblerWithCpp bool // True if .s files should be processed with the c preprocessor.
 
@@ -420,6 +421,7 @@
 type Objects struct {
 	objFiles      android.Paths
 	tidyFiles     android.Paths
+	tidyDepFiles  android.Paths // link dependent .tidy files
 	coverageFiles android.Paths
 	sAbiDumpFiles android.Paths
 	kytheFiles    android.Paths
@@ -429,6 +431,7 @@
 	return Objects{
 		objFiles:      append(android.Paths{}, a.objFiles...),
 		tidyFiles:     append(android.Paths{}, a.tidyFiles...),
+		tidyDepFiles:  append(android.Paths{}, a.tidyDepFiles...),
 		coverageFiles: append(android.Paths{}, a.coverageFiles...),
 		sAbiDumpFiles: append(android.Paths{}, a.sAbiDumpFiles...),
 		kytheFiles:    append(android.Paths{}, a.kytheFiles...),
@@ -439,6 +442,7 @@
 	return Objects{
 		objFiles:      append(a.objFiles, b.objFiles...),
 		tidyFiles:     append(a.tidyFiles, b.tidyFiles...),
+		tidyDepFiles:  append(a.tidyDepFiles, b.tidyDepFiles...),
 		coverageFiles: append(a.coverageFiles, b.coverageFiles...),
 		sAbiDumpFiles: append(a.sAbiDumpFiles, b.sAbiDumpFiles...),
 		kytheFiles:    append(a.kytheFiles, b.kytheFiles...),
@@ -452,9 +456,8 @@
 }
 
 // Generate rules for compiling multiple .c, .cpp, or .S files to individual .o files
-func transformSourceToObj(ctx android.ModuleContext, subdir string, srcFiles, noTidySrcs android.Paths,
+func transformSourceToObj(ctx ModuleContext, subdir string, srcFiles, noTidySrcs android.Paths,
 	flags builderFlags, pathDeps android.Paths, cFlagsDeps android.Paths) Objects {
-
 	// Source files are one-to-one with tidy, coverage, or kythe files, if enabled.
 	objFiles := make(android.Paths, len(srcFiles))
 	var tidyFiles android.Paths
@@ -540,8 +543,7 @@
 	// Multiple source files have build rules usually share the same cFlags or tidyFlags.
 	// Define only one version in this module and share it in multiple build rules.
 	// To simplify the code, the shared variables are all named as $flags<nnn>.
-	numSharedFlags := 0
-	flagsMap := make(map[string]string)
+	shared := ctx.getSharedFlags()
 
 	// Share flags only when there are multiple files or tidy rules.
 	var hasMultipleRules = len(srcFiles) > 1 || flags.tidy
@@ -553,11 +555,11 @@
 			return flags
 		}
 		mapKey := kind + flags
-		n, ok := flagsMap[mapKey]
+		n, ok := shared.flagsMap[mapKey]
 		if !ok {
-			numSharedFlags += 1
-			n = strconv.Itoa(numSharedFlags)
-			flagsMap[mapKey] = n
+			shared.numSharedFlags += 1
+			n = strconv.Itoa(shared.numSharedFlags)
+			shared.flagsMap[mapKey] = n
 			ctx.Variable(pctx, kind+n, flags)
 		}
 		return "$" + kind + n
@@ -720,9 +722,14 @@
 
 	}
 
+	var tidyDepFiles android.Paths
+	if flags.needTidyFiles {
+		tidyDepFiles = tidyFiles
+	}
 	return Objects{
 		objFiles:      objFiles,
 		tidyFiles:     tidyFiles,
+		tidyDepFiles:  tidyDepFiles,
 		coverageFiles: coverageFiles,
 		sAbiDumpFiles: sAbiDumpFiles,
 		kytheFiles:    kytheFiles,
diff --git a/cc/cc.go b/cc/cc.go
index 72adefd..9c35348 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -210,11 +210,12 @@
 	// These must be after any module include flags, which will be in CommonFlags.
 	SystemIncludeFlags []string
 
-	Toolchain    config.Toolchain
-	Tidy         bool // True if clang-tidy is enabled.
-	GcovCoverage bool // True if coverage files should be generated.
-	SAbiDump     bool // True if header abi dumps should be generated.
-	EmitXrefs    bool // If true, generate Ninja rules to generate emitXrefs input files for Kythe
+	Toolchain     config.Toolchain
+	Tidy          bool // True if ninja .tidy rules should be generated.
+	NeedTidyFiles bool // True if module link should depend on .tidy files
+	GcovCoverage  bool // True if coverage files should be generated.
+	SAbiDump      bool // True if header abi dumps should be generated.
+	EmitXrefs     bool // If true, generate Ninja rules to generate emitXrefs input files for Kythe
 
 	// The instruction set required for clang ("arm" or "thumb").
 	RequiredInstructionSet string
@@ -516,6 +517,12 @@
 	directlyInAnyApex() bool
 	isPreventInstall() bool
 	isCfiAssemblySupportEnabled() bool
+	getSharedFlags() *SharedFlags
+}
+
+type SharedFlags struct {
+	numSharedFlags int
+	flagsMap       map[string]string
 }
 
 type ModuleContext interface {
@@ -827,6 +834,9 @@
 	// Flags used to compile this module
 	flags Flags
 
+	// Shared flags among build rules of this module
+	sharedFlags SharedFlags
+
 	// only non-nil when this is a shared library that reuses the objects of a static library
 	staticAnalogue *StaticLibraryInfo
 
@@ -1605,6 +1615,15 @@
 	return ctx.mod.Properties.PreventInstall
 }
 
+func (ctx *moduleContextImpl) getSharedFlags() *SharedFlags {
+	shared := &ctx.mod.sharedFlags
+	if shared.flagsMap == nil {
+		shared.numSharedFlags = 0
+		shared.flagsMap = make(map[string]string)
+	}
+	return shared
+}
+
 func (ctx *moduleContextImpl) isCfiAssemblySupportEnabled() bool {
 	return ctx.mod.isCfiAssemblySupportEnabled()
 }
diff --git a/cc/compiler.go b/cc/compiler.go
index 8adc3ab..9dbf2d1 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -675,7 +675,7 @@
 }
 
 // Compile a list of source files into objects a specified subdirectory
-func compileObjs(ctx android.ModuleContext, flags builderFlags, subdir string,
+func compileObjs(ctx ModuleContext, flags builderFlags, subdir string,
 	srcFiles, noTidySrcs, pathDeps android.Paths, cFlagsDeps android.Paths) Objects {
 
 	return transformSourceToObj(ctx, subdir, srcFiles, noTidySrcs, flags, pathDeps, cFlagsDeps)
diff --git a/cc/library.go b/cc/library.go
index b18f90d..1f9ff7c 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -1340,7 +1340,7 @@
 		}
 	}
 
-	transformObjToStaticLib(ctx, library.objects.objFiles, deps.WholeStaticLibsFromPrebuilts, builderFlags, outputFile, nil, objs.tidyFiles)
+	transformObjToStaticLib(ctx, library.objects.objFiles, deps.WholeStaticLibsFromPrebuilts, builderFlags, outputFile, nil, objs.tidyDepFiles)
 
 	library.coverageOutputFile = transformCoverageFilesToZip(ctx, library.objects, ctx.ModuleName())
 
@@ -1487,7 +1487,7 @@
 	linkerDeps = append(linkerDeps, deps.LateSharedLibsDeps...)
 	transformObjToDynamicBinary(ctx, objs.objFiles, sharedLibs,
 		deps.StaticLibs, deps.LateStaticLibs, deps.WholeStaticLibs,
-		linkerDeps, deps.CrtBegin, deps.CrtEnd, false, builderFlags, outputFile, implicitOutputs, objs.tidyFiles)
+		linkerDeps, deps.CrtBegin, deps.CrtEnd, false, builderFlags, outputFile, implicitOutputs, objs.tidyDepFiles)
 
 	objs.coverageFiles = append(objs.coverageFiles, deps.StaticLibObjs.coverageFiles...)
 	objs.coverageFiles = append(objs.coverageFiles, deps.WholeStaticLibObjs.coverageFiles...)
diff --git a/cc/tidy.go b/cc/tidy.go
index 78a791f..97418fe 100644
--- a/cc/tidy.go
+++ b/cc/tidy.go
@@ -71,13 +71,17 @@
 		return flags
 	}
 
-	// If not explicitly set, check the global tidy flag
-	if tidy.Properties.Tidy == nil && !ctx.Config().ClangTidy() {
-		return flags
-	}
-
+	// If not explicitly disabled, set flags.Tidy to generate .tidy rules.
+	// Note that libraries and binaries will depend on .tidy files ONLY if
+	// the global WITH_TIDY or module 'tidy' property is true.
 	flags.Tidy = true
 
+	// If explicitly enabled, by global default or local tidy property,
+	// set flags.NeedTidyFiles to make this module depend on .tidy files.
+	if ctx.Config().ClangTidy() || Bool(tidy.Properties.Tidy) {
+		flags.NeedTidyFiles = true
+	}
+
 	// Add global WITH_TIDY_FLAGS and local tidy_flags.
 	withTidyFlags := ctx.Config().Getenv("WITH_TIDY_FLAGS")
 	if len(withTidyFlags) > 0 {
diff --git a/cc/util.go b/cc/util.go
index 88b0aba..b256b9a 100644
--- a/cc/util.go
+++ b/cc/util.go
@@ -85,6 +85,7 @@
 		toolchain:     in.Toolchain,
 		gcovCoverage:  in.GcovCoverage,
 		tidy:          in.Tidy,
+		needTidyFiles: in.NeedTidyFiles,
 		sAbiDump:      in.SAbiDump,
 		emitXrefs:     in.EmitXrefs,