Merge "Automate dependency on inputs of genrule module type."
This commit is contained in:
commit
888d92e941
|
@ -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>,"+
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue