diff options
-rw-r--r-- | src/main/java/com/google/devtools/build/lib/rules/SkylarkRuleContext.java | 13 | ||||
-rw-r--r-- | src/test/java/com/google/devtools/build/lib/skylark/SkylarkAspectsTest.java | 31 |
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'", "", "", ""); |