Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 888d92e9 authored by Bill Peckham's avatar Bill Peckham Committed by Gerrit Code Review
Browse files

Merge "Automate dependency on inputs of genrule module type."

parents 578b7ac6 c087be1e
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@ var (
	outputRoot    string
	keepOutDir    bool
	depfileOut    string
	inputHash     string
)

func init() {
@@ -51,6 +52,8 @@ func init() {
	flag.StringVar(&depfileOut, "depfile-out", "",
		"file path of the depfile to generate. This value will replace '__SBOX_DEPFILE__' in the command and will be treated as an output but won't be added to __SBOX_OUT_FILES__")

	flag.StringVar(&inputHash, "input-hash", "",
		"This option is ignored. Typical usage is to supply a hash of the list of input names so that the module will be rebuilt if the list (and thus the hash) changes.")
}

func usageViolation(violation string) {
@@ -59,7 +62,7 @@ func usageViolation(violation string) {
	}

	fmt.Fprintf(os.Stderr,
		"Usage: sbox -c <commandToRun> --sandbox-path <sandboxPath> --output-root <outputRoot> [--depfile-out depFile] <outputFile> [<outputFile>...]\n"+
		"Usage: sbox -c <commandToRun> --sandbox-path <sandboxPath> --output-root <outputRoot> [--depfile-out depFile] [--input-hash hash] <outputFile> [<outputFile>...]\n"+
			"\n"+
			"Deletes <outputRoot>,"+
			"runs <commandToRun>,"+
+21 −2
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import (

	"android/soong/android"
	"android/soong/shared"
	"crypto/sha256"
	"path/filepath"
)

@@ -309,6 +310,7 @@ func (g *Module) GenerateAndroidBuildActions(ctx android.ModuleContext) {
			addLocationLabel(out.Rel(), []string{filepath.Join("__SBOX_OUT_DIR__", out.Rel())})
		}

		referencedIn := false
		referencedDepfile := false

		rawCommand, err := android.ExpandNinjaEscaped(task.cmd, func(name string) (string, bool, error) {
@@ -333,6 +335,7 @@ func (g *Module) GenerateAndroidBuildActions(ctx android.ModuleContext) {
				}
				return locationLabels[firstLabel][0], false, nil
			case "in":
				referencedIn = true
				return "${in}", true, nil
			case "out":
				return "__SBOX_OUT_FILES__", false, nil
@@ -398,8 +401,16 @@ func (g *Module) GenerateAndroidBuildActions(ctx android.ModuleContext) {
		// Escape the command for the shell
		rawCommand = "'" + strings.Replace(rawCommand, "'", `'\''`, -1) + "'"
		g.rawCommands = append(g.rawCommands, rawCommand)
		sandboxCommand := fmt.Sprintf("rm -rf %s && $sboxCmd --sandbox-path %s --output-root %s -c %s %s $allouts",
			task.genDir, sandboxPath, task.genDir, rawCommand, depfilePlaceholder)

		sandboxCommand := fmt.Sprintf("rm -rf %s && $sboxCmd --sandbox-path %s --output-root %s",
			task.genDir, sandboxPath, task.genDir)

		if !referencedIn {
			sandboxCommand = sandboxCommand + hashSrcFiles(srcFiles)
		}

		sandboxCommand = sandboxCommand + fmt.Sprintf(" -c %s %s $allouts",
			rawCommand, depfilePlaceholder)

		ruleParams := blueprint.RuleParams{
			Command:     sandboxCommand,
@@ -463,6 +474,14 @@ func (g *Module) GenerateAndroidBuildActions(ctx android.ModuleContext) {

}

func hashSrcFiles(srcFiles android.Paths) string {
	h := sha256.New()
	for _, src := range srcFiles {
		h.Write([]byte(src.String()))
	}
	return fmt.Sprintf(" --input-hash %x", h.Sum(nil))
}

func (g *Module) generateSourceFile(ctx android.ModuleContext, task generateTask, rule blueprint.Rule) {
	desc := "generate"
	if len(task.out) == 0 {
+87 −0
Original line number Diff line number Diff line
@@ -502,6 +502,93 @@ func TestGenruleCmd(t *testing.T) {
	}
}

func TestGenruleHashInputs(t *testing.T) {

	// The basic idea here is to verify that the sbox command (which is
	// in the Command field of the generate rule) contains a hash of the
	// inputs, but only if $(in) is not referenced in the genrule cmd
	// property.

	// By including a hash of the inputs, we cause the rule to re-run if
	// the list of inputs changes (because the sbox command changes).

	// However, if the genrule cmd property already contains $(in), then
	// the dependency is already expressed, so we don't need to include the
	// hash in that case.

	bp := `
			genrule {
				name: "hash0",
				srcs: ["in1.txt", "in2.txt"],
				out: ["out"],
				cmd: "echo foo > $(out)",
			}
			genrule {
				name: "hash1",
				srcs: ["*.txt"],
				out: ["out"],
				cmd: "echo bar > $(out)",
			}
			genrule {
				name: "hash2",
				srcs: ["*.txt"],
				out: ["out"],
				cmd: "echo $(in) > $(out)",
			}
		`
	testcases := []struct {
		name         string
		expectedHash string
	}{
		{
			name: "hash0",
			// sha256 value obtained from: echo -n 'in1.txtin2.txt' | sha256sum
			expectedHash: "031097e11e0a8c822c960eb9742474f46336360a515744000d086d94335a9cb9",
		},
		{
			name: "hash1",
			// sha256 value obtained from: echo -n 'in1.txtin2.txtin3.txt' | sha256sum
			expectedHash: "de5d22a4a7ab50d250cc59fcdf7a7e0775790d270bfca3a7a9e1f18a70dd996c",
		},
		{
			name: "hash2",
			// $(in) is present, option should not appear
			expectedHash: "",
		},
	}

	config := testConfig(bp, nil)
	ctx := testContext(config)
	_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
	if errs == nil {
		_, errs = ctx.PrepareBuildActions(config)
	}
	if errs != nil {
		t.Fatal(errs)
	}

	for _, test := range testcases {
		t.Run(test.name, func(t *testing.T) {
			gen := ctx.ModuleForTests(test.name, "")
			command := gen.Rule("generator").RuleParams.Command

			if len(test.expectedHash) > 0 {
				// We add spaces before and after to make sure that
				// this option doesn't abutt another sbox option.
				expectedInputHashOption := " --input-hash " + test.expectedHash + " "

				if !strings.Contains(command, expectedInputHashOption) {
					t.Errorf("Expected command \"%s\" to contain \"%s\"", command, expectedInputHashOption)
				}
			} else {
				if strings.Contains(command, "--input-hash") {
					t.Errorf("Unexpected \"--input-hash\" found in command: \"%s\"", command)
				}
			}
		})
	}
}

func TestGenSrcs(t *testing.T) {
	testcases := []struct {
		name string