Fix missing genrule srcs and tools with ALLOW_MISSING_DEPENDENCIES=true
Set the location label for missing srcs and tools to avoid
nonsensical errors when parsing the command.
Test: genrule_test.go
Test: paths_test.go
Test: unbundled branch with missing framework-res module needed by robolectric genrule
Change-Id: I9c1f1cd82a80f048c0e903b8e93910b1ae34b0b1
diff --git a/genrule/genrule.go b/genrule/genrule.go
index e259b1d..87e6747 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -189,6 +189,8 @@
}
if len(g.properties.Tools) > 0 {
+ seenTools := make(map[string]bool)
+
ctx.VisitDirectDepsBlueprint(func(module blueprint.Module) {
switch tag := ctx.OtherModuleDependencyTag(module).(type) {
case hostToolDependencyTag:
@@ -220,11 +222,25 @@
if path.Valid() {
g.deps = append(g.deps, path.Path())
addLocationLabel(tag.label, []string{path.Path().String()})
+ seenTools[tag.label] = true
} else {
ctx.ModuleErrorf("host tool %q missing output file", tool)
}
}
})
+
+ // If AllowMissingDependencies is enabled, the build will not have stopped when
+ // AddFarVariationDependencies was called on a missing tool, which will result in nonsensical
+ // "cmd: unknown location label ..." errors later. Add a dummy file to the local label. The
+ // command that uses this dummy file will never be executed because the rule will be replaced with
+ // an android.Error rule reporting the missing dependencies.
+ if ctx.Config().AllowMissingDependencies() {
+ for _, tool := range g.properties.Tools {
+ if !seenTools[tool] {
+ addLocationLabel(tool, []string{"***missing tool " + tool + "***"})
+ }
+ }
+ }
}
if ctx.Failed() {
@@ -239,9 +255,24 @@
var srcFiles android.Paths
for _, in := range g.properties.Srcs {
- paths := android.PathsForModuleSrcExcludes(ctx, []string{in}, g.properties.Exclude_srcs)
- srcFiles = append(srcFiles, paths...)
- addLocationLabel(in, paths.Strings())
+ paths, missingDeps := android.PathsAndMissingDepsForModuleSrcExcludes(ctx, []string{in}, g.properties.Exclude_srcs)
+ if len(missingDeps) > 0 {
+ if !ctx.Config().AllowMissingDependencies() {
+ panic(fmt.Errorf("should never get here, the missing dependencies %q should have been reported in DepsMutator",
+ missingDeps))
+ }
+
+ // If AllowMissingDependencies is enabled, the build will not have stopped when
+ // the dependency was added on a missing SourceFileProducer module, which will result in nonsensical
+ // "cmd: label ":..." has no files" errors later. Add a dummy file to the local label. The
+ // command that uses this dummy file will never be executed because the rule will be replaced with
+ // an android.Error rule reporting the missing dependencies.
+ ctx.AddMissingDependencies(missingDeps)
+ addLocationLabel(in, []string{"***missing srcs " + in + "***"})
+ } else {
+ srcFiles = append(srcFiles, paths...)
+ addLocationLabel(in, paths.Strings())
+ }
}
task := g.taskGenerator(ctx, String(g.properties.Cmd), srcFiles)
diff --git a/genrule/genrule_test.go b/genrule/genrule_test.go
index 5cb51b8..0b6952f 100644
--- a/genrule/genrule_test.go
+++ b/genrule/genrule_test.go
@@ -17,11 +17,13 @@
import (
"io/ioutil"
"os"
+ "reflect"
"strings"
"testing"
"android/soong/android"
- "reflect"
+
+ "github.com/google/blueprint/proptools"
)
var buildDir string
@@ -123,6 +125,8 @@
name string
prop string
+ allowMissingDependencies bool
+
err string
expect string
}{
@@ -425,6 +429,30 @@
`,
err: "must have at least one output file",
},
+ {
+ name: "srcs allow missing dependencies",
+ prop: `
+ srcs: [":missing"],
+ out: ["out"],
+ cmd: "cat $(location :missing) > $(out)",
+ `,
+
+ allowMissingDependencies: true,
+
+ expect: "cat ***missing srcs :missing*** > __SBOX_OUT_FILES__",
+ },
+ {
+ name: "tool allow missing dependencies",
+ prop: `
+ tools: [":missing"],
+ out: ["out"],
+ cmd: "$(location :missing) > $(out)",
+ `,
+
+ allowMissingDependencies: true,
+
+ expect: "***missing tool :missing*** > __SBOX_OUT_FILES__",
+ },
}
for _, test := range testcases {
@@ -435,7 +463,10 @@
bp += test.prop
bp += "}\n"
+ config.TestProductVariables.Allow_missing_dependencies = proptools.BoolPtr(test.allowMissingDependencies)
+
ctx := testContext(config, bp, nil)
+ ctx.SetAllowMissingDependencies(test.allowMissingDependencies)
_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
if errs == nil {
@@ -460,8 +491,8 @@
}
gen := ctx.ModuleForTests("gen", "").Module().(*Module)
- if gen.rawCommand != "'"+test.expect+"'" {
- t.Errorf("want %q, got %q", test.expect, gen.rawCommand)
+ if g, w := gen.rawCommand, "'"+test.expect+"'"; w != g {
+ t.Errorf("want %q, got %q", w, g)
}
})
}