aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/SkylarkRuleContext.java13
-rw-r--r--src/test/java/com/google/devtools/build/lib/skylark/SkylarkAspectsTest.java31
2 files changed, 43 insertions, 1 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/rules/SkylarkRuleContext.java b/src/main/java/com/google/devtools/build/lib/rules/SkylarkRuleContext.java
index 523c9c758d..8abc00bf51 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/SkylarkRuleContext.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/SkylarkRuleContext.java
@@ -64,6 +64,7 @@ import com.google.devtools.build.lib.vfs.PathFragment;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@@ -279,6 +280,7 @@ public final class SkylarkRuleContext {
Builder<Artifact, FilesToRunProvider> executableRunfilesbuilder = new Builder<>();
Builder<String, Object> fileBuilder = new Builder<>();
Builder<String, Object> filesBuilder = new Builder<>();
+ HashSet<Artifact> seenExecutables = new HashSet<>();
for (Attribute a : attributes) {
Type<?> type = a.getType();
Object val = attributeValueExtractor.apply(a);
@@ -296,7 +298,16 @@ public final class SkylarkRuleContext {
if (provider != null && provider.getExecutable() != null) {
Artifact executable = provider.getExecutable();
executableBuilder.put(skyname, executable);
- executableRunfilesbuilder.put(executable, provider);
+ if (!seenExecutables.contains(executable)) {
+ // todo(dslomov,laurentlb): In general, this is incorrect.
+ // We associate the first encountered FilesToRunProvider with
+ // the executable (this provider is later used to build the spawn).
+ // However ideally we should associate a provider with the attribute name,
+ // and pass the correct FilesToRunProvider to the spawn depending on
+ // what attribute is used to access the executable.
+ executableRunfilesbuilder.put(executable, provider);
+ seenExecutables.add(executable);
+ }
} else {
executableBuilder.put(skyname, Runtime.NONE);
}
diff --git a/src/test/java/com/google/devtools/build/lib/skylark/SkylarkAspectsTest.java b/src/test/java/com/google/devtools/build/lib/skylark/SkylarkAspectsTest.java
index b8489b90e3..d37754897e 100644
--- a/src/test/java/com/google/devtools/build/lib/skylark/SkylarkAspectsTest.java
+++ b/src/test/java/com/google/devtools/build/lib/skylark/SkylarkAspectsTest.java
@@ -580,6 +580,37 @@ public class SkylarkAspectsTest extends AnalysisTestCase {
}
@Test
+ public void multipleExecutablesInTarget() throws Exception {
+ scratch.file("foo/extension.bzl",
+ "def _aspect_impl(target, ctx):",
+ " return struct()",
+ "my_aspect = aspect(_aspect_impl)",
+ "def _main_rule_impl(ctx):",
+ " pass",
+ "my_rule = rule(_main_rule_impl,",
+ " attrs = { ",
+ " 'exe1' : attr.label(executable = True, allow_files = True),",
+ " 'exe2' : attr.label(executable = True, allow_files = True),",
+ " },",
+ ")"
+ );
+
+ scratch.file("foo/tool.sh", "#!/bin/bash");
+ scratch.file("foo/BUILD",
+ "load('extension', 'my_rule')",
+ "my_rule(name = 'main', exe1 = ':tool.sh', exe2 = ':tool.sh')"
+ );
+ AnalysisResult analysisResultOfRule =
+ update(ImmutableList.<String>of(), "//foo:main");
+ assertThat(analysisResultOfRule.hasError()).isFalse();
+
+ AnalysisResult analysisResultOfAspect =
+ update(ImmutableList.<String>of("/foo/extension.bzl%my_aspect"), "//foo:main");
+ assertThat(analysisResultOfAspect.hasError()).isFalse();
+ }
+
+
+ @Test
public void testAspectFragmentAccessSuccess() throws Exception {
getConfiguredTargetForAspectFragment(
"ctx.fragments.cpp.compiler", "'cpp'", "", "", "");