Build dexpreopt_tools.zip in soong

For soong-only builds.

Bug: 398028319
Test: diff'd zip file before/after, they're the same
Change-Id: I6b480f4185546f3b61d81ad80f0fe1db6bafb133
diff --git a/dexpreopt/Android.bp b/dexpreopt/Android.bp
index ea3f52b..dbc1922 100644
--- a/dexpreopt/Android.bp
+++ b/dexpreopt/Android.bp
@@ -9,6 +9,7 @@
         "class_loader_context.go",
         "config.go",
         "dexpreopt.go",
+        "dexpreopt_tools_zip.go",
         "system_server_zip.go",
         "testing.go",
     ],
diff --git a/dexpreopt/dexpreopt_tools_zip.go b/dexpreopt/dexpreopt_tools_zip.go
new file mode 100644
index 0000000..c7cf128
--- /dev/null
+++ b/dexpreopt/dexpreopt_tools_zip.go
@@ -0,0 +1,62 @@
+package dexpreopt
+
+import "android/soong/android"
+
+func init() {
+	android.InitRegistrationContext.RegisterSingletonType("dexpreopt_tools_zip_singleton", dexpreoptToolsZipSingletonFactory)
+}
+
+func dexpreoptToolsZipSingletonFactory() android.Singleton {
+	return &dexpreoptToolsZipSingleton{}
+}
+
+type dexpreoptToolsZipSingleton struct{}
+
+func (s *dexpreoptToolsZipSingleton) GenerateBuildActions(ctx android.SingletonContext) {
+	// The mac build doesn't build dex2oat, so create the zip file only if the build OS is linux.
+	if !ctx.Config().BuildOS.Linux() {
+		return
+	}
+	global := GetGlobalConfig(ctx)
+	if global.DisablePreopt {
+		return
+	}
+	config := GetCachedGlobalSoongConfig(ctx)
+	if config == nil {
+		return
+	}
+
+	deps := android.Paths{
+		ctx.Config().HostToolPath(ctx, "dexpreopt_gen"),
+		ctx.Config().HostToolPath(ctx, "dexdump"),
+		ctx.Config().HostToolPath(ctx, "oatdump"),
+		config.Profman,
+		config.Dex2oat,
+		config.Aapt,
+		config.SoongZip,
+		config.Zip2zip,
+		config.ManifestCheck,
+		config.ConstructContext,
+		config.UffdGcFlag,
+	}
+
+	out := android.PathForOutput(ctx, "dexpreopt_tools.zip")
+	builder := android.NewRuleBuilder(pctx, ctx)
+
+	cmd := builder.Command().BuiltTool("soong_zip").
+		Flag("-d").
+		FlagWithOutput("-o ", out).
+		Flag("-j")
+
+	for _, dep := range deps {
+		cmd.FlagWithInput("-f ", dep)
+	}
+
+	// This reads through a symlink to include the file it points to. This isn't great for
+	// build reproducibility, will need to be revisited later.
+	cmd.Textf("-f $(realpath %s)", config.Dex2oat)
+
+	builder.Build("dexpreopt_tools_zip", "building dexpreopt_tools.zip")
+
+	ctx.DistForGoal("droidcore", out)
+}
diff --git a/java/sdk.go b/java/sdk.go
index ab1c653..73262da 100644
--- a/java/sdk.go
+++ b/java/sdk.go
@@ -382,7 +382,7 @@
 
 	rule.Build("api_fingerprint", "generate api_fingerprint.txt")
 
-	if ctx.Config().BuildOS == android.Linux {
+	if ctx.Config().BuildOS.Linux() {
 		ctx.DistForGoals([]string{"sdk", "droidcore"}, out)
 	}
 }