Remove timestamp based filelist file for tracking Python dependencies

Each Python module will generate a zip file containing source & data
files. The Python binary will collect all its dependencies and use
merge_zips to merge each zip file to create a final .par file.

Test: m -j checkbuild && real examples:
Bug: b/70568913

Change-Id: I9ff232d461d33e1c06026e7dcb5b124bf02c3ce5
diff --git a/python/builder.go b/python/builder.go
index f194354..353054d 100644
--- a/python/builder.go
+++ b/python/builder.go
@@ -17,7 +17,6 @@
 // This file contains Ninja build actions for building Python program.
 
 import (
-	"fmt"
 	"strings"
 
 	"android/soong/android"
@@ -29,25 +28,30 @@
 var (
 	pctx = android.NewPackageContext("android/soong/python")
 
-	host_par = pctx.AndroidStaticRule("host_par",
+	zip = pctx.AndroidStaticRule("zip",
 		blueprint.RuleParams{
-			Command: `touch $initFile && ` +
-				`sed -e 's/%interpreter%/$interp/g' -e 's/%main%/$main/g' $template > $stub && ` +
-				`$parCmd -o $parFile $parArgs && echo '#!/usr/bin/env python' | cat - $parFile > $out && ` +
-				`chmod +x $out && (rm -f $initFile; rm -f $stub; rm -f $parFile)`,
-			CommandDeps: []string{"$parCmd", "$template"},
-		},
-		"initFile", "interp", "main", "template", "stub", "parCmd", "parFile", "parArgs")
-
-	embedded_par = pctx.AndroidStaticRule("embedded_par",
-		blueprint.RuleParams{
-			Command: `touch $initFile && ` +
-				`echo '$main' > $entry_point && ` +
-				`$parCmd -o $parFile $parArgs && cat $launcher | cat - $parFile > $out && ` +
-				`chmod +x $out && (rm -f $initFile; rm -f $entry_point; rm -f $parFile)`,
+			Command:     `$parCmd -o $out $args`,
 			CommandDeps: []string{"$parCmd"},
 		},
-		"initFile", "main", "entry_point", "parCmd", "parFile", "parArgs", "launcher")
+		"args")
+
+	hostPar = pctx.AndroidStaticRule("hostPar",
+		blueprint.RuleParams{
+			Command: `sed -e 's/%interpreter%/$interp/g' -e 's/%main%/$main/g' $template > $stub && ` +
+				`$mergeParCmd -p -pm $stub $mergedZip $srcsZips && echo '#!/usr/bin/env python' | cat - $mergedZip > $out && ` +
+				`chmod +x $out && (rm -f $stub; rm -f $mergedZip)`,
+			CommandDeps: []string{"$mergeParCmd"},
+		},
+		"interp", "main", "template", "stub", "mergedZip", "srcsZips")
+
+	embeddedPar = pctx.AndroidStaticRule("embeddedPar",
+		blueprint.RuleParams{
+			Command: `echo '$main' > $entryPoint &&` +
+				`$mergeParCmd -p -e $entryPoint $mergedZip $srcsZips && cat $launcher | cat - $mergedZip > $out && ` +
+				`chmod +x $out && (rm -f $entryPoint; rm -f $mergedZip)`,
+			CommandDeps: []string{"$mergeParCmd"},
+		},
+		"main", "entryPoint", "mergedZip", "srcsZips", "launcher")
 )
 
 func init() {
@@ -55,132 +59,65 @@
 	pctx.Import("android/soong/common")
 
 	pctx.HostBinToolVariable("parCmd", "soong_zip")
+	pctx.HostBinToolVariable("mergeParCmd", "merge_zips")
 }
 
-type fileListSpec struct {
-	fileList     android.Path
-	relativeRoot string
-}
+func registerBuildActionForParFile(ctx android.ModuleContext, embeddedLauncher bool,
+	launcherPath android.Path, interpreter, main, binName string,
+	srcsZips android.Paths) android.Path {
 
-type parSpec struct {
-	rootPrefix string
-
-	fileListSpecs []fileListSpec
-}
-
-func (p parSpec) soongParArgs() string {
-	ret := `-P ` + p.rootPrefix
-
-	for _, spec := range p.fileListSpecs {
-		ret += ` -C ` + spec.relativeRoot + ` -l ` + spec.fileList.String()
-	}
-
-	return ret
-}
-
-func registerBuildActionForModuleFileList(ctx android.ModuleContext,
-	name string, files android.Paths) android.Path {
-	fileList := android.PathForModuleOut(ctx, name+".list")
-
-	content := []string{}
-	for _, file := range files {
-		content = append(content, file.String())
-	}
-
-	ctx.Build(pctx, android.BuildParams{
-		Rule:        android.WriteFile,
-		Description: "generate " + fileList.Rel(),
-		Output:      fileList,
-		Implicits:   files,
-		Args: map[string]string{
-			"content": strings.Join(content, `\n`),
-		},
-	})
-
-	return fileList
-}
-
-func registerBuildActionForParFile(ctx android.ModuleContext, embedded_launcher bool,
-	launcher_path android.Path, interpreter, main, binName string,
-	newPyPkgs []string, parSpecs []parSpec) android.Path {
-
-	// .intermediate output path for __init__.py
-	initFile := android.PathForModuleOut(ctx, initFileName).String()
-
-	// .intermediate output path for par file.
-	parFile := android.PathForModuleOut(ctx, binName+parFileExt)
+	// .intermediate output path for merged zip file.
+	mergedZip := android.PathForModuleOut(ctx, binName+".mergedzip")
 
 	// .intermediate output path for bin executable.
 	binFile := android.PathForModuleOut(ctx, binName)
 
 	// implicit dependency for parFile build action.
-	implicits := android.Paths{}
-	for _, p := range parSpecs {
-		for _, f := range p.fileListSpecs {
-			implicits = append(implicits, f.fileList)
-		}
-	}
+	implicits := srcsZips
 
-	parArgs := []string{}
-	parArgs = append(parArgs, `-P "" `+`-C `+strings.TrimSuffix(initFile, initFileName)+` -f `+initFile)
-	for _, pkg := range newPyPkgs {
-		parArgs = append(parArgs, `-P `+pkg+` -f `+initFile)
-	}
-	for _, p := range parSpecs {
-		parArgs = append(parArgs, p.soongParArgs())
-	}
-
-	if !embedded_launcher {
+	if !embeddedLauncher {
 		// the path of stub_template_host.txt from source tree.
 		template := android.PathForSource(ctx, stubTemplateHost)
+		implicits = append(implicits, template)
 
 		// intermediate output path for __main__.py
 		stub := android.PathForModuleOut(ctx, mainFileName).String()
 
-		// added stub file to the soong_zip args.
-		parArgs = append(parArgs, `-P "" `+`-C `+strings.TrimSuffix(stub, mainFileName)+` -f `+stub)
-
 		ctx.Build(pctx, android.BuildParams{
-			Rule:        host_par,
+			Rule:        hostPar,
 			Description: "host python archive",
 			Output:      binFile,
 			Implicits:   implicits,
 			Args: map[string]string{
-				"initFile": initFile,
-				"interp":   strings.Replace(interpreter, "/", `\/`, -1),
+				"interp": strings.Replace(interpreter, "/", `\/`, -1),
 				// we need remove "runfiles/" suffix since stub script starts
 				// searching for main file in each sub-dir of "runfiles" directory tree.
 				"main": strings.Replace(strings.TrimPrefix(main, runFiles+"/"),
 					"/", `\/`, -1),
-				"template": template.String(),
-				"stub":     stub,
-				"parFile":  parFile.String(),
-				"parArgs":  strings.Join(parArgs, " "),
+				"template":  template.String(),
+				"stub":      stub,
+				"mergedZip": mergedZip.String(),
+				"srcsZips":  strings.Join(srcsZips.Strings(), " "),
 			},
 		})
 	} else {
-		// added launcher_path to the implicits Ninja dependencies.
-		implicits = append(implicits, launcher_path)
+		// added launcherPath to the implicits Ninja dependencies.
+		implicits = append(implicits, launcherPath)
 
 		// .intermediate output path for entry_point.txt
 		entryPoint := android.PathForModuleOut(ctx, entryPointFile).String()
 
-		// added entry_point file to the soong_zip args.
-		parArgs = append(parArgs, `-P "" `+`-C `+fmt.Sprintf(
-			"%q", strings.TrimSuffix(entryPoint, entryPointFile))+` -f `+entryPoint)
-
 		ctx.Build(pctx, android.BuildParams{
-			Rule:        embedded_par,
+			Rule:        embeddedPar,
 			Description: "embedded python archive",
 			Output:      binFile,
 			Implicits:   implicits,
 			Args: map[string]string{
-				"initFile":    initFile,
-				"main":        main,
-				"entry_point": entryPoint,
-				"parFile":     parFile.String(),
-				"parArgs":     strings.Join(parArgs, " "),
-				"launcher":    launcher_path.String(),
+				"main":       main,
+				"entryPoint": entryPoint,
+				"mergedZip":  mergedZip.String(),
+				"srcsZips":   strings.Join(srcsZips.Strings(), " "),
+				"launcher":   launcherPath.String(),
 			},
 		})
 	}