Package fuzz targets into zipfiles, then coalesce.

Instead of writing all fuzz target files into a huge zipfile (by number
of entries), we instead write each fuzz target and its files to a
zipfile, then coalesce them into a big zipfile.

This should simplify the repackager significantly, as no unzipping and
repackaging should be needed (just renaming).

This also solves b/144418402, where we are very close to hitting the
POSIX args limit on the soong_zip command for the device fuzz package,
due to the line length generated by all the entries in the huge zipfile.

Fixes: 144418402
Test: make fuzz
Change-Id: I89797e1bea2691ff4a33a227306f2f9083d8af6e
diff --git a/cc/fuzz.go b/cc/fuzz.go
index 4b537c0..ef7db79 100644
--- a/cc/fuzz.go
+++ b/cc/fuzz.go
@@ -317,9 +317,10 @@
 			return
 		}
 
-		// Discard vendor-NDK-linked modules, they're duplicates of fuzz targets
-		// we're going to package anyway.
-		if ccModule.UseVndk() || !ccModule.Enabled() {
+		// Discard vendor-NDK-linked + recovery modules, they're duplicates of
+		// fuzz targets we're going to package anyway.
+		if !ccModule.Enabled() || ccModule.Properties.PreventInstall ||
+			ccModule.UseVndk() || ccModule.InRecovery() {
 			return
 		}
 
@@ -337,9 +338,23 @@
 		sharedLibraries := make(map[string]android.Path)
 		collectAllSharedDependencies(module, sharedLibraries, ctx)
 
+		var files []fileToZip
+		builder := android.NewRuleBuilder()
+
+		// Package the corpora into a zipfile.
+		if fuzzModule.corpus != nil {
+			corpusZip := archDir.Join(ctx, module.Name()+"_seed_corpus.zip")
+			command := builder.Command().BuiltTool(ctx, "soong_zip").
+				Flag("-j").
+				FlagWithOutput("-o ", corpusZip)
+			command.FlagWithRspFileInputList("-l ", fuzzModule.corpus)
+			files = append(files, fileToZip{corpusZip, ""})
+		}
+
+		// Find and mark all the transiently-dependent shared libraries for
+		// packaging.
 		for _, library := range sharedLibraries {
-			archDirs[archDir] = append(archDirs[archDir],
-				fileToZip{library, ccModule.Name() + "/lib"})
+			files = append(files, fileToZip{library, "lib"})
 
 			if _, exists := archSharedLibraryDeps[archAndLibraryKey{archDir, library}]; exists {
 				continue
@@ -360,26 +375,35 @@
 		}
 
 		// The executable.
-		archDirs[archDir] = append(archDirs[archDir],
-			fileToZip{ccModule.UnstrippedOutputFile(), ccModule.Name()})
-
-		// The corpora.
-		for _, corpusEntry := range fuzzModule.corpus {
-			archDirs[archDir] = append(archDirs[archDir],
-				fileToZip{corpusEntry, ccModule.Name() + "/corpus"})
-		}
+		files = append(files, fileToZip{ccModule.UnstrippedOutputFile(), ""})
 
 		// The dictionary.
 		if fuzzModule.dictionary != nil {
-			archDirs[archDir] = append(archDirs[archDir],
-				fileToZip{fuzzModule.dictionary, ccModule.Name()})
+			files = append(files, fileToZip{fuzzModule.dictionary, ""})
 		}
 
 		// Additional fuzz config.
 		if fuzzModule.config != nil {
-			archDirs[archDir] = append(archDirs[archDir],
-				fileToZip{fuzzModule.config, ccModule.Name()})
+			files = append(files, fileToZip{fuzzModule.config, ""})
 		}
+
+		fuzzZip := archDir.Join(ctx, module.Name()+".zip")
+		command := builder.Command().BuiltTool(ctx, "soong_zip").
+			Flag("-j").
+			FlagWithOutput("-o ", fuzzZip)
+		for _, file := range files {
+			if file.DestinationPathPrefix != "" {
+				command.FlagWithArg("-P ", file.DestinationPathPrefix)
+			} else {
+				command.Flag("-P ''")
+			}
+			command.FlagWithInput("-f ", file.SourceFilePath)
+		}
+
+		builder.Build(pctx, ctx, "create-"+fuzzZip.String(),
+			"Package "+module.Name()+" for "+archString+"-"+hostOrTargetString)
+
+		archDirs[archDir] = append(archDirs[archDir], fileToZip{fuzzZip, ""})
 	})
 
 	for archDir, filesToZip := range archDirs {
@@ -391,11 +415,16 @@
 
 		command := builder.Command().BuiltTool(ctx, "soong_zip").
 			Flag("-j").
-			FlagWithOutput("-o ", outputFile)
+			FlagWithOutput("-o ", outputFile).
+			Flag("-L 0") // No need to try and re-compress the zipfiles.
 
 		for _, fileToZip := range filesToZip {
-			command.FlagWithArg("-P ", fileToZip.DestinationPathPrefix).
-				FlagWithInput("-f ", fileToZip.SourceFilePath)
+			if fileToZip.DestinationPathPrefix != "" {
+				command.FlagWithArg("-P ", fileToZip.DestinationPathPrefix)
+			} else {
+				command.Flag("-P ''")
+			}
+			command.FlagWithInput("-f ", fileToZip.SourceFilePath)
 		}
 
 		builder.Build(pctx, ctx, "create-fuzz-package-"+arch+"-"+hostOrTarget,