Fix gensrcs subdirs

The depfile was intended to be placed alongside the per-shard
output file, but was in the final directory instead.  Move
it into the per-shard directory.

Also clean up and comment how shards and shard directories
work.

Test: m framework-cppstream-protos
Test: TestGenSrcs
Change-Id: Ia526ae8997314998814ed8e35598cc2a5bc4aabd
diff --git a/genrule/genrule.go b/genrule/genrule.go
index f85146c..b76ca16 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -206,6 +206,7 @@
 	}
 	return ok
 }
+
 func (g *Module) GenerateAndroidBuildActions(ctx android.ModuleContext) {
 	g.subName = ctx.ModuleSubDir()
 
@@ -461,9 +462,10 @@
 		// Create a rule that zips all the per-shard directories into a single zip and then
 		// uses zipsync to unzip it into the final directory.
 		ctx.Build(pctx, android.BuildParams{
-			Rule:      gensrcsMerge,
-			Implicits: copyFrom,
-			Outputs:   outputFiles,
+			Rule:        gensrcsMerge,
+			Implicits:   copyFrom,
+			Outputs:     outputFiles,
+			Description: "merge shards",
 			Args: map[string]string{
 				"zipArgs": zipArgs.String(),
 				"tmpZip":  android.PathForModuleGen(ctx, g.subDir+".zip").String(),
@@ -564,13 +566,19 @@
 func NewGenSrcs() *Module {
 	properties := &genSrcsProperties{}
 
+	// finalSubDir is the name of the subdirectory that output files will be generated into.
+	// It is used so that per-shard directories can be placed alongside it an then finally
+	// merged into it.
+	const finalSubDir = "gensrcs"
+
 	taskGenerator := func(ctx android.ModuleContext, rawCommand string, srcFiles android.Paths) []generateTask {
-		genDir := android.PathForModuleGen(ctx, "gensrcs")
 		shardSize := defaultShardSize
 		if s := properties.Shard_size; s != nil {
 			shardSize = int(*s)
 		}
 
+		// gensrcs rules can easily hit command line limits by repeating the command for
+		// every input file.  Shard the input files into groups.
 		shards := android.ShardPaths(srcFiles, shardSize)
 		var generateTasks []generateTask
 
@@ -578,35 +586,45 @@
 			var commands []string
 			var outFiles android.WritablePaths
 			var copyTo android.WritablePaths
-			var shardDir android.WritablePath
 			var depFile android.WritablePath
 
+			// When sharding is enabled (i.e. len(shards) > 1), the sbox rules for each
+			// shard will be write to their own directories and then be merged together
+			// into finalSubDir.  If sharding is not enabled (i.e. len(shards) == 1),
+			// the sbox rule will write directly to finalSubDir.
+			genSubDir := finalSubDir
 			if len(shards) > 1 {
-				shardDir = android.PathForModuleGen(ctx, strconv.Itoa(i))
-			} else {
-				shardDir = genDir
+				genSubDir = strconv.Itoa(i)
 			}
 
-			for j, in := range shard {
-				outFile := android.GenPathWithExt(ctx, "gensrcs", in, String(properties.Output_extension))
-				if j == 0 {
-					depFile = outFile.ReplaceExtension(ctx, "d")
-				}
+			genDir := android.PathForModuleGen(ctx, genSubDir)
 
+			for j, in := range shard {
+				outFile := android.GenPathWithExt(ctx, finalSubDir, in, String(properties.Output_extension))
+
+				// If sharding is enabled, then outFile is the path to the output file in
+				// the shard directory, and copyTo is the path to the output file in the
+				// final directory.
 				if len(shards) > 1 {
-					shardFile := android.GenPathWithExt(ctx, strconv.Itoa(i), in, String(properties.Output_extension))
+					shardFile := android.GenPathWithExt(ctx, genSubDir, in, String(properties.Output_extension))
 					copyTo = append(copyTo, outFile)
 					outFile = shardFile
 				}
 
+				if j == 0 {
+					depFile = outFile.ReplaceExtension(ctx, "d")
+				}
+
 				outFiles = append(outFiles, outFile)
 
+				// pre-expand the command line to replace $in and $out with references to
+				// a single input and output file.
 				command, err := android.Expand(rawCommand, func(name string) (string, error) {
 					switch name {
 					case "in":
 						return in.String(), nil
 					case "out":
-						return android.SboxPathForOutput(outFile, shardDir), nil
+						return android.SboxPathForOutput(outFile, genDir), nil
 					default:
 						return "$(" + name + ")", nil
 					}
@@ -626,7 +644,7 @@
 				out:     outFiles,
 				depFile: depFile,
 				copyTo:  copyTo,
-				genDir:  shardDir,
+				genDir:  genDir,
 				cmd:     fullCommand,
 				shard:   i,
 				shards:  len(shards),
@@ -637,7 +655,7 @@
 	}
 
 	g := generatorFactory(taskGenerator, properties)
-	g.subDir = "gensrcs"
+	g.subDir = finalSubDir
 	return g
 }