diff --git a/src/main/java/com/google/devtools/build/lib/rules/genrule/GenRuleBase.java b/src/main/java/com/google/devtools/build/lib/rules/genrule/GenRuleBase.java
index 7228f4b7e8ede6..2b2ab5ce667f7c 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/genrule/GenRuleBase.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/genrule/GenRuleBase.java
@@ -309,6 +309,15 @@ public String lookupVariable(String variableName) throws ExpansionException {
return expandSingletonArtifact(filesToBuild, "$@", "output file");
}
+ if (variableName.equals("RULEDIR")) {
+ // The output root directory. This variable expands to the package's root directory
+ // in the genfiles tree.
+ PathFragment dir = ruleContext.getBinOrGenfilesDirectory().getExecPath();
+ PathFragment relPath =
+ ruleContext.getRule().getLabel().getPackageIdentifier().getSourceRoot();
+ return dir.getRelative(relPath).getPathString();
+ }
+
if (variableName.equals("@D")) {
// The output directory. If there is only one filename in outs,
// this expands to the directory containing that file. If there are
diff --git a/src/main/java/com/google/devtools/build/lib/rules/genrule/GenRuleBaseRule.java b/src/main/java/com/google/devtools/build/lib/rules/genrule/GenRuleBaseRule.java
index c0287c3da63b0c..3534938e146b7c 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/genrule/GenRuleBaseRule.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/genrule/GenRuleBaseRule.java
@@ -131,9 +131,10 @@ public RuleClass build(
list, not in srcs
, to ensure they are built in the correct configuration.
@@ -161,8 +162,8 @@ public RuleClass build(
Note that outs
are not included in this substitution. Output files
are always generated into a predictable location (available via $(@D)
,
- $@
, $(OUTS)
or $(location output_name)
;
- see below).
+ $@
, $(OUTS)
or $(RULEDIR)
or
+ $(location output_name)
; see below).
For example, FilePath.create("foo/bar/wiz").relativeTo(FilePath.create("foo"))
- * returns "bar/wiz"
.
+ *
For example,
+ * {@link PathFragment}.create("foo/bar/wiz").relativeTo({@link PathFragment}.create("foo"))
+ *
returns "bar/wiz"
.
*
*
If the {@link PathFragment} is not a child of the passed {@link PathFragment} an {@link * IllegalArgumentException} is thrown. In particular, this will happen whenever the two {@link diff --git a/src/test/java/com/google/devtools/build/lib/bazel/rules/genrule/GenRuleConfiguredTargetTest.java b/src/test/java/com/google/devtools/build/lib/bazel/rules/genrule/GenRuleConfiguredTargetTest.java index ece88bdf6fdbe8..a8e9bbbf0185f1 100644 --- a/src/test/java/com/google/devtools/build/lib/bazel/rules/genrule/GenRuleConfiguredTargetTest.java +++ b/src/test/java/com/google/devtools/build/lib/bazel/rules/genrule/GenRuleConfiguredTargetTest.java @@ -283,6 +283,26 @@ public void testOutputDirExpansion() throws Exception { assertThat(bazExpected.equals(barExpected)).isFalse(); } + /** Ensure that variable $(RULE_DIR) gets expanded correctly in the genrule cmd. */ + @Test + public void testRuleDirExpansion() throws Exception { + scratch.file( + "foo/BUILD", + "genrule(name = 'bar',", + " srcs = ['bar_in.txt'],", + " cmd = 'touch $(RULEDIR)',", + " outs = ['bar/bar_out.txt'])", + "genrule(name = 'baz',", + " srcs = ['bar/bar_out.txt'],", + " cmd = 'touch $(RULEDIR)',", + " outs = ['baz/baz_out.txt', 'logs/baz.log'])"); + + // Make sure the expansion for $(RULE_DIR) results in the directory of the BUILD file ("foo") + String expectedRegex = "touch b.{4}-out.*foo"; + assertThat(getCommand("//foo:bar")).containsMatch(expectedRegex); + assertThat(getCommand("//foo:baz")).containsMatch(expectedRegex); + } + /** Ensure that variable $(CC) gets expanded correctly in the genrule cmd. */ @Test public void testMakeVarExpansion() throws Exception {