Rewrite depfile from sbox to stay reproducible

sbox will generate a random directory for the output root, and most
tools will encode that directory name in the output target of the
depfile.

So embed the library from dep_fixer into sbox so that it can rewrite the
output filename to a static (reproducible) value. Ninja doesn't care
what that value is, so it's just "outputfile".

Also fix up rule_builder to actually tell sbox about the depfile.

Bug: 144948629
Test: mmma system/iorap; check the contents of:
out/soong/.intermediates/system/iorap/libiorap-binder/android_arm_armv7-a-neon_core_static/gen/aidl/system/iorap/binder/com/google/android/startop/iorap/IIorap.cpp.d

Change-Id: I3640a2e8b0c034f143a35e398a8418a6d621b265
Merged-In: I3640a2e8b0c034f143a35e398a8418a6d621b265
(cherry picked from commit c89b6f19810d368d7d5c128407c3eaaa5e3b2e81)
diff --git a/android/rule_builder.go b/android/rule_builder.go
index 4a3b022..b3fccea 100644
--- a/android/rule_builder.go
+++ b/android/rule_builder.go
@@ -342,10 +342,6 @@
 			sboxOutputs[i] = "__SBOX_OUT_DIR__/" + Rel(ctx, r.sboxOutDir.String(), output.String())
 		}
 
-		if depFile != nil {
-			sboxOutputs = append(sboxOutputs, "__SBOX_OUT_DIR__/"+Rel(ctx, r.sboxOutDir.String(), depFile.String()))
-		}
-
 		commandString = proptools.ShellEscape(commandString)
 		if !strings.HasPrefix(commandString, `'`) {
 			commandString = `'` + commandString + `'`
@@ -355,8 +351,13 @@
 		sboxCmd.Tool(ctx.Config().HostToolPath(ctx, "sbox")).
 			Flag("-c").Text(commandString).
 			Flag("--sandbox-path").Text(shared.TempDirForOutDir(PathForOutput(ctx).String())).
-			Flag("--output-root").Text(r.sboxOutDir.String()).
-			Flags(sboxOutputs)
+			Flag("--output-root").Text(r.sboxOutDir.String())
+
+		if depFile != nil {
+			sboxCmd.Flag("--depfile-out").Text(depFile.String())
+		}
+
+		sboxCmd.Flags(sboxOutputs)
 
 		commandString = string(sboxCmd.buf)
 		tools = append(tools, sboxCmd.tools...)
diff --git a/android/rule_builder_test.go b/android/rule_builder_test.go
index df0f256..d122a42 100644
--- a/android/rule_builder_test.go
+++ b/android/rule_builder_test.go
@@ -454,6 +454,7 @@
 	FailIfErrored(t, errs)
 
 	check := func(t *testing.T, params TestingBuildParams, wantCommand, wantOutput, wantDepfile string, wantRestat bool, extraCmdDeps []string) {
+		t.Helper()
 		if params.RuleParams.Command != wantCommand {
 			t.Errorf("\nwant RuleParams.Command = %q\n                      got %q", wantCommand, params.RuleParams.Command)
 		}
@@ -497,13 +498,14 @@
 	t.Run("sbox", func(t *testing.T) {
 		outDir := filepath.Join(buildDir, ".intermediates", "foo_sbox")
 		outFile := filepath.Join(outDir, "foo_sbox")
+		depFile := filepath.Join(outDir, "foo_sbox.d")
 		sbox := filepath.Join(buildDir, "host", config.PrebuiltOS(), "bin/sbox")
 		sandboxPath := shared.TempDirForOutDir(buildDir)
 
-		cmd := sbox + ` -c 'cp bar __SBOX_OUT_DIR__/foo_sbox' --sandbox-path ` + sandboxPath + " --output-root " + outDir + " __SBOX_OUT_DIR__/foo_sbox __SBOX_OUT_DIR__/foo_sbox.d"
+		cmd := sbox + ` -c 'cp bar __SBOX_OUT_DIR__/foo_sbox' --sandbox-path ` + sandboxPath + " --output-root " + outDir + " --depfile-out " + depFile + " __SBOX_OUT_DIR__/foo_sbox"
 
 		check(t, ctx.ModuleForTests("foo_sbox", "").Rule("rule"),
-			cmd, outFile, outFile+".d", false, []string{sbox})
+			cmd, outFile, depFile, false, []string{sbox})
 	})
 	t.Run("singleton", func(t *testing.T) {
 		outFile := filepath.Join(buildDir, "baz")
diff --git a/cmd/dep_fixer/Android.bp b/cmd/dep_fixer/Android.bp
index d2d1113..97364d5 100644
--- a/cmd/dep_fixer/Android.bp
+++ b/cmd/dep_fixer/Android.bp
@@ -14,10 +14,6 @@
 
 blueprint_go_binary {
     name: "dep_fixer",
-    deps: ["androidmk-parser"],
-    srcs: [
-        "main.go",
-        "deps.go",
-    ],
-    testSrcs: ["deps_test.go"],
+    deps: ["soong-makedeps"],
+    srcs: ["main.go"],
 }
diff --git a/cmd/dep_fixer/main.go b/cmd/dep_fixer/main.go
index f94cf2f..d1bd139 100644
--- a/cmd/dep_fixer/main.go
+++ b/cmd/dep_fixer/main.go
@@ -25,6 +25,8 @@
 	"io/ioutil"
 	"log"
 	"os"
+
+	"android/soong/makedeps"
 )
 
 func main() {
@@ -39,7 +41,7 @@
 		log.Fatal("Expected at least one input file as an argument")
 	}
 
-	var mergedDeps *Deps
+	var mergedDeps *makedeps.Deps
 	var firstInput []byte
 
 	for i, arg := range flag.Args() {
@@ -48,7 +50,7 @@
 			log.Fatalf("Error opening %q: %v", arg, err)
 		}
 
-		deps, err := Parse(arg, bytes.NewBuffer(append([]byte(nil), input...)))
+		deps, err := makedeps.Parse(arg, bytes.NewBuffer(append([]byte(nil), input...)))
 		if err != nil {
 			log.Fatalf("Failed to parse: %v", err)
 		}
diff --git a/cmd/sbox/Android.bp b/cmd/sbox/Android.bp
index fe4c7bb..a706810d 100644
--- a/cmd/sbox/Android.bp
+++ b/cmd/sbox/Android.bp
@@ -14,6 +14,7 @@
 
 blueprint_go_binary {
     name: "sbox",
+    deps: ["soong-makedeps"],
     srcs: [
         "sbox.go",
     ],
diff --git a/cmd/sbox/sbox.go b/cmd/sbox/sbox.go
index 4ac9295..7057b33 100644
--- a/cmd/sbox/sbox.go
+++ b/cmd/sbox/sbox.go
@@ -15,6 +15,7 @@
 package main
 
 import (
+	"bytes"
 	"errors"
 	"flag"
 	"fmt"
@@ -25,6 +26,8 @@
 	"path/filepath"
 	"strings"
 	"time"
+
+	"android/soong/makedeps"
 )
 
 var (
@@ -152,9 +155,6 @@
 			return err
 		}
 		allOutputs = append(allOutputs, sandboxedDepfile)
-		if !strings.Contains(rawCommand, "__SBOX_DEPFILE__") {
-			return fmt.Errorf("the --depfile-out argument only makes sense if the command contains the text __SBOX_DEPFILE__")
-		}
 		rawCommand = strings.Replace(rawCommand, "__SBOX_DEPFILE__", filepath.Join(tempDir, sandboxedDepfile), -1)
 
 	}
@@ -281,6 +281,26 @@
 		}
 	}
 
+	// Rewrite the depfile so that it doesn't include the (randomized) sandbox directory
+	if depfileOut != "" {
+		in, err := ioutil.ReadFile(depfileOut)
+		if err != nil {
+			return err
+		}
+
+		deps, err := makedeps.Parse(depfileOut, bytes.NewBuffer(in))
+		if err != nil {
+			return err
+		}
+
+		deps.Output = "outputfile"
+
+		err = ioutil.WriteFile(depfileOut, deps.Print(), 0666)
+		if err != nil {
+			return err
+		}
+	}
+
 	// TODO(jeffrygaston) if a process creates more output files than it declares, should there be a warning?
 	return nil
 }
diff --git a/makedeps/Android.bp b/makedeps/Android.bp
new file mode 100644
index 0000000..b77b08f
--- /dev/null
+++ b/makedeps/Android.bp
@@ -0,0 +1,21 @@
+// Copyright 2019 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+bootstrap_go_package {
+    name: "soong-makedeps",
+    pkgPath: "android/soong/makedeps",
+    deps: ["androidmk-parser"],
+    srcs: ["deps.go"],
+    testSrcs: ["deps_test.go"],
+}
diff --git a/cmd/dep_fixer/deps.go b/makedeps/deps.go
similarity index 98%
rename from cmd/dep_fixer/deps.go
rename to makedeps/deps.go
index 64c97f5..e64e6f7 100644
--- a/cmd/dep_fixer/deps.go
+++ b/makedeps/deps.go
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package main
+package makedeps
 
 import (
 	"bytes"
diff --git a/cmd/dep_fixer/deps_test.go b/makedeps/deps_test.go
similarity index 99%
rename from cmd/dep_fixer/deps_test.go
rename to makedeps/deps_test.go
index 0a779b7..a32df65 100644
--- a/cmd/dep_fixer/deps_test.go
+++ b/makedeps/deps_test.go
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package main
+package makedeps
 
 import (
 	"bytes"