Implement OutputGroupInfo provider.
Work towards #2894.
RELNOTES: None.
PiperOrigin-RevId: 154829065
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/AnalysisUtils.java b/src/main/java/com/google/devtools/build/lib/analysis/AnalysisUtils.java
index 01004d1..7159395 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/AnalysisUtils.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/AnalysisUtils.java
@@ -82,14 +82,15 @@
* Returns the list of declared providers (native and Skylark) of the specified Skylark key from a
* set of transitive info collections.
*/
- public static Iterable<SkylarkClassObject> getProviders(
+ public static <T extends SkylarkClassObject> Iterable<T> getProviders(
Iterable<? extends TransitiveInfoCollection> prerequisites,
- final ClassObjectConstructor.Key skylarkKey) {
- ImmutableList.Builder<SkylarkClassObject> result = ImmutableList.builder();
+ final ClassObjectConstructor.Key skylarkKey,
+ Class<T> resultClass) {
+ ImmutableList.Builder<T> result = ImmutableList.builder();
for (TransitiveInfoCollection prerequisite : prerequisites) {
SkylarkClassObject prerequisiteProvider = prerequisite.get(skylarkKey);
if (prerequisiteProvider != null) {
- result.add(prerequisiteProvider);
+ result.add(resultClass.cast(prerequisiteProvider));
}
}
return result.build();
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredAspect.java b/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredAspect.java
index 6b7c031..18c00f9 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredAspect.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredAspect.java
@@ -30,11 +30,13 @@
import com.google.devtools.build.lib.packages.AspectDescriptor;
import com.google.devtools.build.lib.packages.AspectParameters;
import com.google.devtools.build.lib.packages.ClassObjectConstructor;
+import com.google.devtools.build.lib.packages.ClassObjectConstructor.Key;
import com.google.devtools.build.lib.packages.SkylarkClassObject;
import com.google.devtools.build.lib.packages.SkylarkClassObjectConstructor;
import com.google.devtools.build.lib.syntax.EvalException;
import com.google.devtools.build.lib.util.Preconditions;
import java.util.Arrays;
+import java.util.LinkedHashMap;
import java.util.Map;
import java.util.TreeMap;
import javax.annotation.Nullable;
@@ -116,8 +118,8 @@
private final Map<String, NestedSetBuilder<Artifact>> outputGroupBuilders = new TreeMap<>();
private final ImmutableMap.Builder<String, Object> skylarkProviderBuilder =
ImmutableMap.builder();
- private final ImmutableMap.Builder<SkylarkClassObjectConstructor.Key, SkylarkClassObject>
- skylarkDeclaredProvidersBuilder = ImmutableMap.builder();
+ private final LinkedHashMap<Key, SkylarkClassObject>
+ skylarkDeclaredProvidersBuilder = new LinkedHashMap<>();
private final RuleContext ruleContext;
private final AspectDescriptor descriptor;
@@ -212,6 +214,14 @@
return this;
}
+ public Builder addNativeDeclaredProvider(SkylarkClassObject declaredProvider) {
+ ClassObjectConstructor constructor = declaredProvider.getConstructor();
+ Preconditions.checkState(constructor.isExported());
+ skylarkDeclaredProvidersBuilder.put(constructor.getKey(), declaredProvider);
+ return this;
+ }
+
+
public ConfiguredAspect build() {
if (!outputGroupBuilders.isEmpty()) {
ImmutableMap.Builder<String, NestedSet<Artifact>> outputGroups = ImmutableMap.builder();
@@ -219,16 +229,19 @@
outputGroups.put(entry.getKey(), entry.getValue().build());
}
- if (providers.contains(OutputGroupProvider.class)) {
+ if (skylarkDeclaredProvidersBuilder.containsKey(
+ OutputGroupProvider.SKYLARK_CONSTRUCTOR.getKey())) {
throw new IllegalStateException(
"OutputGroupProvider was provided explicitly; do not use addOutputGroup");
}
- addProvider(new OutputGroupProvider(outputGroups.build()));
+ skylarkDeclaredProvidersBuilder.put(
+ OutputGroupProvider.SKYLARK_CONSTRUCTOR.getKey(),
+ new OutputGroupProvider(outputGroups.build()));
}
ImmutableMap<String, Object> skylarkProvidersMap = skylarkProviderBuilder.build();
ImmutableMap<SkylarkClassObjectConstructor.Key, SkylarkClassObject>
- skylarkDeclaredProvidersMap = skylarkDeclaredProvidersBuilder.build();
+ skylarkDeclaredProvidersMap = ImmutableMap.copyOf(skylarkDeclaredProvidersBuilder);
if (!skylarkProvidersMap.isEmpty() || !skylarkDeclaredProvidersMap.isEmpty()) {
providers.add(new SkylarkProviders(skylarkProvidersMap, skylarkDeclaredProvidersMap));
}
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/MergedConfiguredTarget.java b/src/main/java/com/google/devtools/build/lib/analysis/MergedConfiguredTarget.java
index fcd4e91..2c0fcfb 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/MergedConfiguredTarget.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/MergedConfiguredTarget.java
@@ -17,6 +17,8 @@
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
+import com.google.devtools.build.lib.packages.SkylarkClassObject;
+import com.google.devtools.build.lib.packages.SkylarkClassObjectConstructor;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@@ -85,16 +87,23 @@
// Merge output group providers.
OutputGroupProvider mergedOutputGroupProvider =
- OutputGroupProvider.merge(getAllProviders(base, aspects, OutputGroupProvider.class));
+ OutputGroupProvider.merge(getAllOutputGroupProviders(base, aspects));
// Merge Skylark providers.
- ImmutableMap<String, Object> premergedProviders =
+ ImmutableMap<String, Object> premergedLegacyProviders =
mergedOutputGroupProvider == null
- ? ImmutableMap.<String, Object>of()
- : ImmutableMap.<String, Object>of(
- OutputGroupProvider.SKYLARK_NAME, mergedOutputGroupProvider);
+ ? ImmutableMap.<String, Object>of()
+ : ImmutableMap.<String, Object>of(
+ OutputGroupProvider.SKYLARK_NAME, mergedOutputGroupProvider);
+
+ ImmutableMap<SkylarkClassObjectConstructor.Key, SkylarkClassObject> premergedProviders =
+ mergedOutputGroupProvider == null
+ ? ImmutableMap.<SkylarkClassObjectConstructor.Key, SkylarkClassObject>of()
+ : ImmutableMap.<SkylarkClassObjectConstructor.Key, SkylarkClassObject>of(
+ OutputGroupProvider.SKYLARK_CONSTRUCTOR.getKey(), mergedOutputGroupProvider);
SkylarkProviders mergedSkylarkProviders =
SkylarkProviders.merge(
+ premergedLegacyProviders,
premergedProviders,
getAllProviders(base, aspects, SkylarkProviders.class));
@@ -103,9 +112,6 @@
getAllProviders(base, aspects, ExtraActionArtifactsProvider.class));
TransitiveInfoProviderMap.Builder aspectProviders = TransitiveInfoProviderMap.builder();
- if (mergedOutputGroupProvider != null) {
- aspectProviders.add(mergedOutputGroupProvider);
- }
if (mergedSkylarkProviders != null) {
aspectProviders.add(mergedSkylarkProviders);
}
@@ -117,8 +123,7 @@
for (Map.Entry<Class<? extends TransitiveInfoProvider>, TransitiveInfoProvider> entry :
aspect.getProviders().entrySet()) {
Class<? extends TransitiveInfoProvider> providerClass = entry.getKey();
- if (OutputGroupProvider.class.equals(providerClass)
- || SkylarkProviders.class.equals(providerClass)
+ if (SkylarkProviders.class.equals(providerClass)
|| ExtraActionArtifactsProvider.class.equals(providerClass)) {
continue;
}
@@ -133,6 +138,24 @@
return new MergedConfiguredTarget(base, aspectProviders.build());
}
+ private static ImmutableList<OutputGroupProvider> getAllOutputGroupProviders(
+ ConfiguredTarget base, Iterable<ConfiguredAspect> aspects) {
+ OutputGroupProvider baseProvider = OutputGroupProvider.get(base);
+ ImmutableList.Builder<OutputGroupProvider> providers = ImmutableList.builder();
+ if (baseProvider != null) {
+ providers.add(baseProvider);
+ }
+
+ for (ConfiguredAspect configuredAspect : aspects) {
+ OutputGroupProvider aspectProvider = OutputGroupProvider.get(configuredAspect);;
+ if (aspectProvider == null) {
+ continue;
+ }
+ providers.add(aspectProvider);
+ }
+ return providers.build();
+ }
+
private static <T extends TransitiveInfoProvider> List<T> getAllProviders(
ConfiguredTarget base, Iterable<ConfiguredAspect> aspects, Class<T> providerClass) {
T baseProvider = base.getProvider(providerClass);
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/OutputGroupProvider.java b/src/main/java/com/google/devtools/build/lib/analysis/OutputGroupProvider.java
index 7ba2eff..397d7fd 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/OutputGroupProvider.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/OutputGroupProvider.java
@@ -16,6 +16,7 @@
import static com.google.devtools.build.lib.syntax.EvalUtils.SKYLARK_COMPARATOR;
+import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;
@@ -27,6 +28,9 @@
import com.google.devtools.build.lib.collect.nestedset.Order;
import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
import com.google.devtools.build.lib.events.Location;
+import com.google.devtools.build.lib.packages.NativeClassObjectConstructor;
+import com.google.devtools.build.lib.packages.SkylarkClassObject;
+import com.google.devtools.build.lib.rules.SkylarkRuleConfiguredTargetBuilder;
import com.google.devtools.build.lib.syntax.EvalException;
import com.google.devtools.build.lib.syntax.EvalUtils;
import com.google.devtools.build.lib.syntax.SkylarkIndexable;
@@ -34,6 +38,8 @@
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
import java.util.Set;
import javax.annotation.Nullable;
@@ -51,10 +57,12 @@
* not mentioned on the output.
*/
@Immutable
-public final class OutputGroupProvider implements
- TransitiveInfoProvider, SkylarkIndexable, Iterable<String> {
+public final class OutputGroupProvider extends SkylarkClassObject
+ implements SkylarkIndexable, Iterable<String> {
public static final String SKYLARK_NAME = "output_groups";
+ public static NativeClassObjectConstructor SKYLARK_CONSTRUCTOR = new Constructor();
+
/**
* Prefix for output groups that are not reported to the user on the terminal output of Blaze when
* they are built.
@@ -113,9 +121,26 @@
private final ImmutableMap<String, NestedSet<Artifact>> outputGroups;
public OutputGroupProvider(ImmutableMap<String, NestedSet<Artifact>> outputGroups) {
+ super(SKYLARK_CONSTRUCTOR, ImmutableMap.<String, Object>of());
this.outputGroups = outputGroups;
}
+ @Nullable
+ public static OutputGroupProvider get(TransitiveInfoCollection collection) {
+ return (OutputGroupProvider) collection.get(SKYLARK_CONSTRUCTOR.getKey());
+ }
+
+ @Nullable
+ public static OutputGroupProvider get(ConfiguredAspect aspect) {
+ SkylarkProviders skylarkProviders = aspect.getProvider(SkylarkProviders.class);
+
+
+ return skylarkProviders != null
+ ? (OutputGroupProvider) skylarkProviders.getDeclaredProvider(SKYLARK_CONSTRUCTOR.getKey())
+ : null;
+ }
+
+
/** Return the artifacts in a particular output group.
*
* @return the artifacts in the output group with the given name. The return value is never null.
@@ -210,7 +235,6 @@
"Output group %s not present", key
));
}
-
}
@Override
@@ -222,4 +246,51 @@
public Iterator<String> iterator() {
return SKYLARK_COMPARATOR.sortedCopy(outputGroups.keySet()).iterator();
}
+
+ @Override
+ public Object getValue(String name) {
+ NestedSet<Artifact> result = outputGroups.get(name);
+ if (result == null) {
+ return null;
+ }
+ return SkylarkNestedSet.of(Artifact.class, result);
+ }
+
+ @Override
+ public ImmutableCollection<String> getKeys() {
+ return outputGroups.keySet();
+ }
+
+ /**
+ * A constructor callable from Skylark for OutputGroupProvider.
+ */
+ private static class Constructor extends NativeClassObjectConstructor {
+
+ private Constructor() {
+ super("OutputGroupInfo");
+ }
+
+ @Override
+ protected SkylarkClassObject createInstanceFromSkylark(Object[] args, Location loc)
+ throws EvalException {
+
+ @SuppressWarnings("unchecked")
+ Map<String, Object> kwargs = (Map<String, Object>) args[0];
+
+ ImmutableMap.Builder<String, NestedSet<Artifact>> builder = ImmutableMap.builder();
+ for (Entry<String, Object> entry : kwargs.entrySet()) {
+ builder.put(entry.getKey(),
+ SkylarkRuleConfiguredTargetBuilder.convertToOutputGroupValue(
+ loc, entry.getKey(), entry.getValue()));
+
+
+ }
+ return new OutputGroupProvider(builder.build());
+ }
+
+ @Override
+ public String getErrorMessageFormatForInstances() {
+ return "Output group %s not present";
+ }
+ }
}
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/RuleConfiguredTargetBuilder.java b/src/main/java/com/google/devtools/build/lib/analysis/RuleConfiguredTargetBuilder.java
index 6a9c6d6..bdf8e10 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/RuleConfiguredTargetBuilder.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/RuleConfiguredTargetBuilder.java
@@ -131,7 +131,7 @@
}
OutputGroupProvider outputGroupProvider = new OutputGroupProvider(outputGroups.build());
- addProvider(OutputGroupProvider.class, outputGroupProvider);
+ addNativeDeclaredProvider(outputGroupProvider);
addSkylarkTransitiveInfo(OutputGroupProvider.SKYLARK_NAME, outputGroupProvider);
}
@@ -294,6 +294,9 @@
* Adds a "declared provider" defined in Skylark to the rule.
* Use this method for declared providers defined in Skyark.
*
+ * Has special handling for {@link OutputGroupProvider}: that provider is not added
+ * from Skylark directly, instead its outpuyt groups are added.
+ *
* Use {@link #addNativeDeclaredProvider(SkylarkClassObject)} in definitions of
* native rules.
*/
@@ -304,7 +307,14 @@
throw new EvalException(constructor.getLocation(),
"All providers must be top level values");
}
- skylarkDeclaredProviders.put(constructor.getKey(), provider);
+ if (OutputGroupProvider.SKYLARK_CONSTRUCTOR.getKey().equals(constructor.getKey())) {
+ OutputGroupProvider outputGroupProvider = (OutputGroupProvider) provider;
+ for (String outputGroup : outputGroupProvider) {
+ addOutputGroup(outputGroup, outputGroupProvider.getOutputGroup(outputGroup));
+ }
+ } else {
+ skylarkDeclaredProviders.put(constructor.getKey(), provider);
+ }
return this;
}
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java b/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java
index f47b38d..30007e6 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java
@@ -857,9 +857,11 @@
* Returns all the declared providers (native and Skylark) for the specified constructor under the
* specified attribute of this target in the BUILD file.
*/
- public Iterable<SkylarkClassObject> getPrerequisites(
- String attributeName, Mode mode, final ClassObjectConstructor.Key skylarkKey) {
- return AnalysisUtils.getProviders(getPrerequisites(attributeName, mode), skylarkKey);
+ public <T extends SkylarkClassObject> Iterable<T> getPrerequisites(
+ String attributeName, Mode mode,
+ final ClassObjectConstructor.Key skylarkKey,
+ Class<T> result) {
+ return AnalysisUtils.getProviders(getPrerequisites(attributeName, mode), skylarkKey, result);
}
/**
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/SkylarkProviders.java b/src/main/java/com/google/devtools/build/lib/analysis/SkylarkProviders.java
index 05c9c34..0778ade 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/SkylarkProviders.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/SkylarkProviders.java
@@ -20,6 +20,7 @@
import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
import com.google.devtools.build.lib.packages.ClassObjectConstructor;
import com.google.devtools.build.lib.packages.SkylarkClassObject;
+import com.google.devtools.build.lib.packages.SkylarkClassObjectConstructor;
import com.google.devtools.build.lib.packages.SkylarkProviderIdentifier;
import com.google.devtools.build.lib.rules.SkylarkApiProvider;
import com.google.devtools.build.lib.syntax.EvalException;
@@ -124,7 +125,8 @@
* @param providers providers to merge {@code this} with.
*/
public static SkylarkProviders merge(
- Map<String, Object> premergedProviders,
+ ImmutableMap<String, Object> premergedLegacyProviders,
+ ImmutableMap<SkylarkClassObjectConstructor.Key, SkylarkClassObject> premergedProviders,
List<SkylarkProviders> providers)
throws DuplicateException {
if (premergedProviders.size() == 0 && providers.size() == 0) {
@@ -136,11 +138,11 @@
ImmutableMap<String, Object> skylarkProviders = mergeMaps(providers,
SKYLARK_PROVIDERS_MAP_FUNCTION,
- premergedProviders);
+ premergedLegacyProviders);
ImmutableMap<ClassObjectConstructor.Key, SkylarkClassObject> declaredProviders =
mergeMaps(providers, DECLARED_PROVIDERS_MAP_FUNCTION,
- ImmutableMap.<ClassObjectConstructor.Key, SkylarkClassObject>of());
+ premergedProviders);
return new SkylarkProviders(skylarkProviders, declaredProviders);
}
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/TopLevelArtifactHelper.java b/src/main/java/com/google/devtools/build/lib/analysis/TopLevelArtifactHelper.java
index 6665918..a9b77b4 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/TopLevelArtifactHelper.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/TopLevelArtifactHelper.java
@@ -169,7 +169,7 @@
public static ArtifactsToBuild getAllArtifactsToBuild(TransitiveInfoCollection target,
TopLevelArtifactContext context) {
return getAllArtifactsToBuild(
- target.getProvider(OutputGroupProvider.class),
+ OutputGroupProvider.get(target),
target.getProvider(FileProvider.class),
context
);
@@ -179,7 +179,7 @@
AspectValue aspectValue, TopLevelArtifactContext context) {
ConfiguredAspect configuredAspect = aspectValue.getConfiguredAspect();
return getAllArtifactsToBuild(
- configuredAspect.getProvider(OutputGroupProvider.class),
+ OutputGroupProvider.get(configuredAspect),
configuredAspect.getProvider(FileProvider.class),
context);
}
diff --git a/src/main/java/com/google/devtools/build/lib/buildtool/BuildResultPrinter.java b/src/main/java/com/google/devtools/build/lib/buildtool/BuildResultPrinter.java
index 8ef4a38..2d036ee 100644
--- a/src/main/java/com/google/devtools/build/lib/buildtool/BuildResultPrinter.java
+++ b/src/main/java/com/google/devtools/build/lib/buildtool/BuildResultPrinter.java
@@ -33,7 +33,6 @@
import com.google.devtools.build.lib.runtime.CommandEnvironment;
import com.google.devtools.build.lib.skyframe.AspectValue;
import com.google.devtools.build.lib.util.io.OutErr;
-
import java.util.ArrayList;
import java.util.Collection;
@@ -129,7 +128,7 @@
// For failed compilation, it is still useful to examine temp artifacts,
// (ie, preprocessed and assembler files).
OutputGroupProvider topLevelProvider =
- target.getProvider(OutputGroupProvider.class);
+ OutputGroupProvider.get(target);
String productName = env.getRuntime().getProductName();
if (topLevelProvider != null) {
for (Artifact temp : topLevelProvider.getOutputGroup(OutputGroupProvider.TEMP_FILES)) {
diff --git a/src/main/java/com/google/devtools/build/lib/rules/SkylarkRuleClassFunctions.java b/src/main/java/com/google/devtools/build/lib/rules/SkylarkRuleClassFunctions.java
index aefdfaf..733f331 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/SkylarkRuleClassFunctions.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/SkylarkRuleClassFunctions.java
@@ -209,6 +209,14 @@
)
private static final ClassObjectConstructor defaultInfo = DefaultProvider.SKYLARK_CONSTRUCTOR;
+ @SkylarkSignature(
+ name = "OutputGroupInfo",
+ returnType = ClassObjectConstructor.class,
+ doc = "todo"
+ )
+ private static final ClassObjectConstructor outputGroupInfo =
+ OutputGroupProvider.SKYLARK_CONSTRUCTOR;
+
// TODO(bazel-team): Move to a "testing" namespace module. Normally we'd pass an objectType
// to @SkylarkSignature to do this, but that doesn't work here because we're exposing an already-
// configured BaseFunction, rather than defining a new BuiltinFunction. This should wait for
@@ -1047,7 +1055,7 @@
)
private static final BuiltinFunction output_group = new BuiltinFunction("output_group") {
public SkylarkNestedSet invoke(TransitiveInfoCollection self, String group) {
- OutputGroupProvider provider = self.getProvider(OutputGroupProvider.class);
+ OutputGroupProvider provider = OutputGroupProvider.get(self);
NestedSet<Artifact> result = provider != null
? provider.getOutputGroup(group)
: NestedSetBuilder.<Artifact>emptySet(Order.STABLE_ORDER);
diff --git a/src/main/java/com/google/devtools/build/lib/rules/SkylarkRuleConfiguredTargetBuilder.java b/src/main/java/com/google/devtools/build/lib/rules/SkylarkRuleConfiguredTargetBuilder.java
index 5129570..f6900a2 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/SkylarkRuleConfiguredTargetBuilder.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/SkylarkRuleConfiguredTargetBuilder.java
@@ -197,7 +197,7 @@
}
public static NestedSet<Artifact> convertToOutputGroupValue(Location loc, String outputGroup,
- SkylarkValue objects) throws EvalException {
+ Object objects) throws EvalException {
NestedSet<Artifact> artifacts;
String typeErrorMessage =
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidCommon.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidCommon.java
index 7657427..922d87e 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidCommon.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidCommon.java
@@ -39,6 +39,8 @@
import com.google.devtools.build.lib.packages.AttributeMap;
import com.google.devtools.build.lib.packages.BuildType;
import com.google.devtools.build.lib.packages.Rule;
+import com.google.devtools.build.lib.packages.SkylarkClassObject;
+import com.google.devtools.build.lib.packages.SkylarkClassObjectConstructor;
import com.google.devtools.build.lib.rules.android.ResourceContainer.ResourceType;
import com.google.devtools.build.lib.rules.cpp.CcLinkParams;
import com.google.devtools.build.lib.rules.cpp.CcLinkParamsProvider;
@@ -95,6 +97,20 @@
return builder.build();
}
+ public static final <T extends SkylarkClassObject> Iterable<T> getTransitivePrerequisites(
+ RuleContext ruleContext, Mode mode, SkylarkClassObjectConstructor.Key key,
+ final Class<T> classType) {
+ IterablesChain.Builder<T> builder = IterablesChain.builder();
+ AttributeMap attributes = ruleContext.attributes();
+ for (String attr : TRANSITIVE_ATTRIBUTES) {
+ if (attributes.has(attr, BuildType.LABEL_LIST)) {
+ builder.add(ruleContext.getPrerequisites(attr, mode, key, classType));
+ }
+ }
+ return builder.build();
+ }
+
+
public static final Iterable<TransitiveInfoCollection> collectTransitiveInfo(
RuleContext ruleContext, Mode mode) {
ImmutableList.Builder<TransitiveInfoCollection> builder = ImmutableList.builder();
@@ -894,7 +910,9 @@
private NestedSet<Artifact> collectHiddenTopLevelArtifacts(RuleContext ruleContext) {
NestedSetBuilder<Artifact> builder = NestedSetBuilder.stableOrder();
for (OutputGroupProvider provider :
- getTransitivePrerequisites(ruleContext, Mode.TARGET, OutputGroupProvider.class)) {
+ getTransitivePrerequisites(ruleContext, Mode.TARGET,
+ OutputGroupProvider.SKYLARK_CONSTRUCTOR.getKey(),
+ OutputGroupProvider.class)) {
builder.addTransitive(provider.getOutputGroup(OutputGroupProvider.HIDDEN_TOP_LEVEL));
}
return builder.build();
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLibrary.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLibrary.java
index 3d727ae..86f3184 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLibrary.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLibrary.java
@@ -314,7 +314,9 @@
ccCompilationOutputs.getFilesToCompile(
isLipoCollector, processHeadersInDependencies, usePic));
for (OutputGroupProvider dep :
- ruleContext.getPrerequisites("deps", Mode.TARGET, OutputGroupProvider.class)) {
+ ruleContext.getPrerequisites("deps", Mode.TARGET,
+ OutputGroupProvider.SKYLARK_CONSTRUCTOR.getKey(),
+ OutputGroupProvider.class)) {
artifactsToForceBuilder.addTransitive(
dep.getOutputGroup(OutputGroupProvider.HIDDEN_TOP_LEVEL));
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLibraryHelper.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLibraryHelper.java
index 35b39ee..3aaab4d 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLibraryHelper.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLibraryHelper.java
@@ -1484,7 +1484,8 @@
RuleContext ruleContext, CcCompilationOutputs ccCompilationOutputs) {
NestedSetBuilder<Artifact> headerTokens = NestedSetBuilder.stableOrder();
for (OutputGroupProvider dep :
- ruleContext.getPrerequisites("deps", Mode.TARGET, OutputGroupProvider.class)) {
+ ruleContext.getPrerequisites("deps", Mode.TARGET,
+ OutputGroupProvider.SKYLARK_CONSTRUCTOR.getKey(), OutputGroupProvider.class)) {
headerTokens.addTransitive(dep.getOutputGroup(CcLibraryHelper.HIDDEN_HEADER_TOKENS));
}
if (ruleContext.getFragment(CppConfiguration.class).processHeadersInDependencies()) {
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/proto/CcProtoAspect.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/proto/CcProtoAspect.java
index b7395a9..d4d9463 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/proto/CcProtoAspect.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/proto/CcProtoAspect.java
@@ -317,11 +317,12 @@
}
public void addProviders(ConfiguredAspect.Builder builder) {
+ OutputGroupProvider outputGroupProvider = new OutputGroupProvider(outputGroups);
builder.addProvider(
new CcProtoLibraryProviders(
- filesBuilder.build(),
- ccLibraryProviders.toBuilder().add(new OutputGroupProvider(outputGroups)).build()));
+ filesBuilder.build(), ccLibraryProviders, outputGroupProvider));
builder.addProviders(ccLibraryProviders);
+ builder.addNativeDeclaredProvider(outputGroupProvider);
if (headerProvider != null) {
builder.addProvider(headerProvider);
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/proto/CcProtoLibrary.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/proto/CcProtoLibrary.java
index 1f03ef1..d6a5763 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/proto/CcProtoLibrary.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/proto/CcProtoLibrary.java
@@ -45,11 +45,17 @@
checkNotNull(ruleContext.getPrerequisite("deps", TARGET))
.getProvider(CcProtoLibraryProviders.class);
- return new RuleConfiguredTargetBuilder(ruleContext)
+ RuleConfiguredTargetBuilder ruleConfiguredTargetBuilder = new RuleConfiguredTargetBuilder(
+ ruleContext)
.setFilesToBuild(depProviders.filesBuilder)
.addProvider(
RunfilesProvider.class, RunfilesProvider.withData(Runfiles.EMPTY, Runfiles.EMPTY))
- .addProviders(depProviders.providerMap)
+ .addProviders(depProviders.providerMap);
+ for (String groupName : depProviders.outputGroupProvider) {
+ ruleConfiguredTargetBuilder.addOutputGroup(groupName,
+ depProviders.outputGroupProvider.getOutputGroup(groupName));
+ }
+ return ruleConfiguredTargetBuilder
.addSkylarkTransitiveInfo(CcSkylarkApiProvider.NAME, new CcSkylarkApiProvider())
.build();
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/proto/CcProtoLibraryProviders.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/proto/CcProtoLibraryProviders.java
index 35b53d8..f9bb826 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/proto/CcProtoLibraryProviders.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/proto/CcProtoLibraryProviders.java
@@ -15,6 +15,7 @@
package com.google.devtools.build.lib.rules.cpp.proto;
import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.analysis.OutputGroupProvider;
import com.google.devtools.build.lib.analysis.TransitiveInfoProvider;
import com.google.devtools.build.lib.analysis.TransitiveInfoProviderMap;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
@@ -28,9 +29,13 @@
final class CcProtoLibraryProviders implements TransitiveInfoProvider {
final NestedSet<Artifact> filesBuilder;
final TransitiveInfoProviderMap providerMap;
+ final OutputGroupProvider outputGroupProvider;
- CcProtoLibraryProviders(NestedSet<Artifact> filesBuilder, TransitiveInfoProviderMap providerMap) {
+ CcProtoLibraryProviders(NestedSet<Artifact> filesBuilder,
+ TransitiveInfoProviderMap providerMap,
+ OutputGroupProvider outputGroupProvider) {
this.filesBuilder = filesBuilder;
this.providerMap = providerMap;
+ this.outputGroupProvider = outputGroupProvider;
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/filegroup/Filegroup.java b/src/main/java/com/google/devtools/build/lib/rules/filegroup/Filegroup.java
index e359e18..02504be 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/filegroup/Filegroup.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/filegroup/Filegroup.java
@@ -128,7 +128,7 @@
NestedSetBuilder<Artifact> result = NestedSetBuilder.stableOrder();
for (TransitiveInfoCollection dep : deps) {
- OutputGroupProvider outputGroupProvider = dep.getProvider(OutputGroupProvider.class);
+ OutputGroupProvider outputGroupProvider = OutputGroupProvider.get(dep);
if (outputGroupProvider != null) {
result.addTransitive(outputGroupProvider.getOutputGroup(outputGroupName));
}
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/util/BuildViewTestCase.java b/src/test/java/com/google/devtools/build/lib/analysis/util/BuildViewTestCase.java
index a41b3b6..866830f 100644
--- a/src/test/java/com/google/devtools/build/lib/analysis/util/BuildViewTestCase.java
+++ b/src/test/java/com/google/devtools/build/lib/analysis/util/BuildViewTestCase.java
@@ -666,7 +666,7 @@
protected Action getGeneratingActionInOutputGroup(
ConfiguredTarget target, String outputName, String outputGroupName) {
NestedSet<Artifact> outputGroup =
- target.getProvider(OutputGroupProvider.class).getOutputGroup(outputGroupName);
+ OutputGroupProvider.get(target).getOutputGroup(outputGroupName);
return getGeneratingAction(outputName, outputGroup, "outputGroup/" + outputGroupName);
}
@@ -1401,7 +1401,7 @@
protected NestedSet<Artifact> getOutputGroup(
TransitiveInfoCollection target, String outputGroup) {
- OutputGroupProvider provider = target.getProvider(OutputGroupProvider.class);
+ OutputGroupProvider provider = OutputGroupProvider.get(target);
return provider == null
? NestedSetBuilder.<Artifact>emptySet(Order.STABLE_ORDER)
: provider.getOutputGroup(outputGroup);
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 a52ee89..59b637e 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
@@ -421,13 +421,46 @@
update(ImmutableList.of("test/aspect.bzl%MyAspect"), "//test:xxx");
assertThat(getLabelsToBuild(analysisResult)).containsExactly("//test:xxx");
AspectValue aspectValue = analysisResult.getAspects().iterator().next();
- OutputGroupProvider outputGroupProvider =
- aspectValue.getConfiguredAspect().getProvider(OutputGroupProvider.class);
+ OutputGroupProvider outputGroupProvider = OutputGroupProvider.get(
+ aspectValue.getConfiguredAspect());
+
assertThat(outputGroupProvider).isNotNull();
NestedSet<Artifact> names = outputGroupProvider.getOutputGroup("my_result");
assertThat(names).isNotEmpty();
- NestedSet<Artifact> expectedSet = getConfiguredTarget("//test:xxx")
- .getProvider(OutputGroupProvider.class)
+ NestedSet<Artifact> expectedSet = OutputGroupProvider.get(getConfiguredTarget("//test:xxx"))
+ .getOutputGroup(OutputGroupProvider.HIDDEN_TOP_LEVEL);
+ assertThat(names).containsExactlyElementsIn(expectedSet);
+ }
+
+ @Test
+ public void aspectWithOutputGroupsDeclaredProvider() throws Exception {
+ scratch.file(
+ "test/aspect.bzl",
+ "def _impl(target, ctx):",
+ " f = target[OutputGroupInfo]._hidden_top_level" + INTERNAL_SUFFIX,
+ " return [OutputGroupInfo(my_result = f)]",
+ "",
+ "MyAspect = aspect(",
+ " implementation=_impl,",
+ ")");
+ scratch.file(
+ "test/BUILD",
+ "java_library(",
+ " name = 'xxx',",
+ " srcs = ['A.java'],",
+ ")");
+
+ AnalysisResult analysisResult =
+ update(ImmutableList.of("test/aspect.bzl%MyAspect"), "//test:xxx");
+ assertThat(getLabelsToBuild(analysisResult)).containsExactly("//test:xxx");
+ AspectValue aspectValue = analysisResult.getAspects().iterator().next();
+ OutputGroupProvider outputGroupProvider = OutputGroupProvider.get(
+ aspectValue.getConfiguredAspect());
+
+ assertThat(outputGroupProvider).isNotNull();
+ NestedSet<Artifact> names = outputGroupProvider.getOutputGroup("my_result");
+ assertThat(names).isNotEmpty();
+ NestedSet<Artifact> expectedSet = OutputGroupProvider.get(getConfiguredTarget("//test:xxx"))
.getOutputGroup(OutputGroupProvider.HIDDEN_TOP_LEVEL);
assertThat(names).containsExactlyElementsIn(expectedSet);
}
@@ -465,12 +498,53 @@
.containsExactly("//test:xxx");
AspectValue aspectValue = analysisResult.getAspects().iterator().next();
OutputGroupProvider outputGroupProvider =
- aspectValue.getConfiguredAspect().getProvider(OutputGroupProvider.class);
+ OutputGroupProvider.get(aspectValue.getConfiguredAspect());
assertThat(outputGroupProvider).isNotNull();
NestedSet<Artifact> names = outputGroupProvider.getOutputGroup("my_result");
assertThat(names).isNotEmpty();
- NestedSet<Artifact> expectedSet = getConfiguredTarget("//test:xxx")
- .getProvider(OutputGroupProvider.class)
+ NestedSet<Artifact> expectedSet = OutputGroupProvider.get(getConfiguredTarget("//test:xxx"))
+ .getOutputGroup(OutputGroupProvider.HIDDEN_TOP_LEVEL);
+ assertThat(names).containsExactlyElementsIn(expectedSet);
+ }
+
+ @Test
+ public void aspectWithOutputGroupsAsListDeclaredProvider() throws Exception {
+ scratch.file(
+ "test/aspect.bzl",
+ "def _impl(target, ctx):",
+ " g = target[OutputGroupInfo]._hidden_top_level" + INTERNAL_SUFFIX,
+ " return [OutputGroupInfo(my_result= [ f for f in g])]",
+ "",
+ "MyAspect = aspect(",
+ " implementation=_impl,",
+ ")");
+ scratch.file(
+ "test/BUILD",
+ "java_library(",
+ " name = 'xxx',",
+ " srcs = ['A.java'],",
+ ")");
+
+ AnalysisResult analysisResult =
+ update(ImmutableList.of("test/aspect.bzl%MyAspect"), "//test:xxx");
+ assertThat(
+ transform(
+ analysisResult.getTargetsToBuild(),
+ new Function<ConfiguredTarget, String>() {
+ @Nullable
+ @Override
+ public String apply(ConfiguredTarget configuredTarget) {
+ return configuredTarget.getLabel().toString();
+ }
+ }))
+ .containsExactly("//test:xxx");
+ AspectValue aspectValue = analysisResult.getAspects().iterator().next();
+ OutputGroupProvider outputGroupProvider =
+ OutputGroupProvider.get(aspectValue.getConfiguredAspect());
+ assertThat(outputGroupProvider).isNotNull();
+ NestedSet<Artifact> names = outputGroupProvider.getOutputGroup("my_result");
+ assertThat(names).isNotEmpty();
+ NestedSet<Artifact> expectedSet = OutputGroupProvider.get(getConfiguredTarget("//test:xxx"))
.getOutputGroup(OutputGroupProvider.HIDDEN_TOP_LEVEL);
assertThat(names).containsExactlyElementsIn(expectedSet);
}
@@ -863,6 +937,69 @@
}
@Test
+ public void outputGroupsFromOneAspect() throws Exception {
+ scratch.file(
+ "test/aspect.bzl",
+ "def _a1_impl(target, ctx):",
+ " f = ctx.new_file(target.label.name + '_a1.txt')",
+ " ctx.file_action(f, 'f')",
+ " return struct(output_groups = { 'a1_group' : depset([f]) })",
+ "",
+ "a1 = aspect(implementation=_a1_impl, attr_aspects = ['dep'])",
+ "def _rule_impl(ctx):",
+ " if not ctx.attr.dep:",
+ " return struct()",
+ " og = {k:ctx.attr.dep.output_groups[k] for k in ctx.attr.dep.output_groups}",
+ " return struct(output_groups = og)",
+ "my_rule1 = rule(_rule_impl, attrs = { 'dep' : attr.label(aspects = [a1]) })"
+ );
+ scratch.file(
+ "test/BUILD",
+ "load(':aspect.bzl', 'my_rule1')",
+ "my_rule1(name = 'base')",
+ "my_rule1(name = 'xxx', dep = ':base')"
+ );
+
+
+ AnalysisResult analysisResult = update("//test:xxx");
+ OutputGroupProvider outputGroupProvider =
+ OutputGroupProvider.get(Iterables.getOnlyElement(analysisResult.getTargetsToBuild()));
+ assertThat(getOutputGroupContents(outputGroupProvider, "a1_group"))
+ .containsExactly("test/base_a1.txt");
+ }
+
+ @Test
+ public void outputGroupsDeclaredProviderFromOneAspect() throws Exception {
+ scratch.file(
+ "test/aspect.bzl",
+ "def _a1_impl(target, ctx):",
+ " f = ctx.new_file(target.label.name + '_a1.txt')",
+ " ctx.file_action(f, 'f')",
+ " return [OutputGroupInfo(a1_group = depset([f]))]",
+ "",
+ "a1 = aspect(implementation=_a1_impl, attr_aspects = ['dep'])",
+ "def _rule_impl(ctx):",
+ " if not ctx.attr.dep:",
+ " return struct()",
+ " return [OutputGroupInfo(a1_group = ctx.attr.dep[OutputGroupInfo].a1_group)]",
+ "my_rule1 = rule(_rule_impl, attrs = { 'dep' : attr.label(aspects = [a1]) })"
+ );
+ scratch.file(
+ "test/BUILD",
+ "load(':aspect.bzl', 'my_rule1')",
+ "my_rule1(name = 'base')",
+ "my_rule1(name = 'xxx', dep = ':base')"
+ );
+
+
+ AnalysisResult analysisResult = update("//test:xxx");
+ OutputGroupProvider outputGroupProvider =
+ OutputGroupProvider.get(Iterables.getOnlyElement(analysisResult.getTargetsToBuild()));
+ assertThat(getOutputGroupContents(outputGroupProvider, "a1_group"))
+ .containsExactly("test/base_a1.txt");
+ }
+
+ @Test
public void outputGroupsFromTwoAspects() throws Exception {
scratch.file(
"test/aspect.bzl",
@@ -896,9 +1033,7 @@
AnalysisResult analysisResult = update("//test:yyy");
OutputGroupProvider outputGroupProvider =
- Iterables
- .getOnlyElement(analysisResult.getTargetsToBuild())
- .getProvider(OutputGroupProvider.class);
+ OutputGroupProvider.get(Iterables.getOnlyElement(analysisResult.getTargetsToBuild()));
assertThat(getOutputGroupContents(outputGroupProvider, "a1_group"))
.containsExactly("test/base_a1.txt");
assertThat(getOutputGroupContents(outputGroupProvider, "a2_group"))
@@ -906,6 +1041,53 @@
}
@Test
+ public void outputGroupsDeclaredProvidersFromTwoAspects() throws Exception {
+ scratch.file(
+ "test/aspect.bzl",
+ "def _a1_impl(target, ctx):",
+ " f = ctx.new_file(target.label.name + '_a1.txt')",
+ " ctx.file_action(f, 'f')",
+ " return [OutputGroupInfo(a1_group = depset([f]))]",
+ "",
+ "a1 = aspect(implementation=_a1_impl, attr_aspects = ['dep'])",
+ "def _rule_impl(ctx):",
+ " if not ctx.attr.dep:",
+ " return struct()",
+ " og = dict()",
+ " dep_og = ctx.attr.dep[OutputGroupInfo]",
+ " if hasattr(dep_og, 'a1_group'):",
+ " og['a1_group'] = dep_og.a1_group",
+ " if hasattr(dep_og, 'a2_group'):",
+ " og['a2_group'] = dep_og.a2_group",
+ " return [OutputGroupInfo(**og)]",
+ "my_rule1 = rule(_rule_impl, attrs = { 'dep' : attr.label(aspects = [a1]) })",
+ "def _a2_impl(target, ctx):",
+ " g = ctx.new_file(target.label.name + '_a2.txt')",
+ " ctx.file_action(g, 'f')",
+ " return [OutputGroupInfo(a2_group = depset([g]))]",
+ "",
+ "a2 = aspect(implementation=_a2_impl, attr_aspects = ['dep'])",
+ "my_rule2 = rule(_rule_impl, attrs = { 'dep' : attr.label(aspects = [a2]) })");
+ scratch.file(
+ "test/BUILD",
+ "load(':aspect.bzl', 'my_rule1', 'my_rule2')",
+ "my_rule1(name = 'base')",
+ "my_rule1(name = 'xxx', dep = ':base')",
+ "my_rule2(name = 'yyy', dep = ':xxx')"
+ );
+
+
+ AnalysisResult analysisResult = update("//test:yyy");
+ OutputGroupProvider outputGroupProvider =
+ OutputGroupProvider.get(Iterables.getOnlyElement(analysisResult.getTargetsToBuild()));
+ assertThat(getOutputGroupContents(outputGroupProvider, "a1_group"))
+ .containsExactly("test/base_a1.txt");
+ assertThat(getOutputGroupContents(outputGroupProvider, "a2_group"))
+ .containsExactly("test/xxx_a2.txt");
+ }
+
+
+ @Test
public void duplicateOutputGroupsFromTwoAspects() throws Exception {
scratch.file(
"test/aspect.bzl",
diff --git a/src/test/java/com/google/devtools/build/lib/skylark/SkylarkIntegrationTest.java b/src/test/java/com/google/devtools/build/lib/skylark/SkylarkIntegrationTest.java
index 52dcc45..02abf939 100644
--- a/src/test/java/com/google/devtools/build/lib/skylark/SkylarkIntegrationTest.java
+++ b/src/test/java/com/google/devtools/build/lib/skylark/SkylarkIntegrationTest.java
@@ -175,8 +175,7 @@
"cc_binary(name = 'lib', data = ['a.txt'])",
"my_rule(name='my', dep = ':lib')");
NestedSet<Artifact> hiddenTopLevelArtifacts =
- getConfiguredTarget("//test/skylark:lib")
- .getProvider(OutputGroupProvider.class)
+ OutputGroupProvider.get(getConfiguredTarget("//test/skylark:lib"))
.getOutputGroup(OutputGroupProvider.HIDDEN_TOP_LEVEL);
ConfiguredTarget myTarget = getConfiguredTarget("//test/skylark:my");
SkylarkNestedSet result =
@@ -184,11 +183,40 @@
.getProvider(SkylarkProviders.class)
.getValue("result");
assertThat(result.getSet(Artifact.class)).containsExactlyElementsIn(hiddenTopLevelArtifacts);
- assertThat(myTarget.getProvider(OutputGroupProvider.class).getOutputGroup("my_group"))
+ assertThat(OutputGroupProvider.get(myTarget).getOutputGroup("my_group"))
.containsExactlyElementsIn(hiddenTopLevelArtifacts);
}
@Test
+ public void testOutputGroupsDeclaredProvider() throws Exception {
+ scratch.file(
+ "test/skylark/extension.bzl",
+ "def _impl(ctx):",
+ " f = ctx.attr.dep[OutputGroupInfo]._hidden_top_level" + INTERNAL_SUFFIX,
+ " return struct(result = f, ",
+ " providers = [OutputGroupInfo(my_group = f)])",
+ "my_rule = rule(implementation = _impl,",
+ " attrs = { 'dep' : attr.label() })");
+ scratch.file(
+ "test/skylark/BUILD",
+ "load('/test/skylark/extension', 'my_rule')",
+ "cc_binary(name = 'lib', data = ['a.txt'])",
+ "my_rule(name='my', dep = ':lib')");
+ NestedSet<Artifact> hiddenTopLevelArtifacts =
+ OutputGroupProvider.get(getConfiguredTarget("//test/skylark:lib"))
+ .getOutputGroup(OutputGroupProvider.HIDDEN_TOP_LEVEL);
+ ConfiguredTarget myTarget = getConfiguredTarget("//test/skylark:my");
+ SkylarkNestedSet result =
+ (SkylarkNestedSet) myTarget
+ .getProvider(SkylarkProviders.class)
+ .getValue("result");
+ assertThat(result.getSet(Artifact.class)).containsExactlyElementsIn(hiddenTopLevelArtifacts);
+ assertThat(OutputGroupProvider.get(myTarget).getOutputGroup("my_group"))
+ .containsExactlyElementsIn(hiddenTopLevelArtifacts);
+ }
+
+
+ @Test
public void testOutputGroupsAsDictionary() throws Exception {
scratch.file(
"test/skylark/extension.bzl",
@@ -210,15 +238,13 @@
"cc_binary(name = 'lib', data = ['a.txt'])",
"my_rule(name='my', dep = ':lib')");
NestedSet<Artifact> hiddenTopLevelArtifacts =
- getConfiguredTarget("//test/skylark:lib")
- .getProvider(OutputGroupProvider.class)
+ OutputGroupProvider.get(getConfiguredTarget("//test/skylark:lib"))
.getOutputGroup(OutputGroupProvider.HIDDEN_TOP_LEVEL);
ConfiguredTarget myTarget = getConfiguredTarget("//test/skylark:my");
- SkylarkProviders skylarkProviders = myTarget
- .getProvider(SkylarkProviders.class);
+ SkylarkProviders skylarkProviders = myTarget.getProvider(SkylarkProviders.class);
SkylarkNestedSet result = (SkylarkNestedSet) skylarkProviders.getValue("result");
assertThat(result.getSet(Artifact.class)).containsExactlyElementsIn(hiddenTopLevelArtifacts);
- assertThat(myTarget.getProvider(OutputGroupProvider.class).getOutputGroup("my_group"))
+ assertThat(OutputGroupProvider.get(myTarget).getOutputGroup("my_group"))
.containsExactlyElementsIn(hiddenTopLevelArtifacts);
assertThat(skylarkProviders.getValue("has_key1")).isEqualTo(Boolean.TRUE);
assertThat(skylarkProviders.getValue("has_key2")).isEqualTo(Boolean.FALSE);
@@ -247,15 +273,14 @@
"cc_binary(name = 'lib', data = ['a.txt'])",
"my_rule(name='my', dep = ':lib')");
NestedSet<Artifact> hiddenTopLevelArtifacts =
- getConfiguredTarget("//test/skylark:lib")
- .getProvider(OutputGroupProvider.class)
+ OutputGroupProvider.get(getConfiguredTarget("//test/skylark:lib"))
.getOutputGroup(OutputGroupProvider.HIDDEN_TOP_LEVEL);
ConfiguredTarget myTarget = getConfiguredTarget("//test/skylark:my");
SkylarkProviders skylarkProviders = myTarget
.getProvider(SkylarkProviders.class);
SkylarkNestedSet result = (SkylarkNestedSet) skylarkProviders.getValue("result");
assertThat(result.getSet(Artifact.class)).containsExactlyElementsIn(hiddenTopLevelArtifacts);
- assertThat(myTarget.getProvider(OutputGroupProvider.class).getOutputGroup("my_group"))
+ assertThat(OutputGroupProvider.get(myTarget).getOutputGroup("my_group"))
.containsExactlyElementsIn(hiddenTopLevelArtifacts);
}
@@ -276,18 +301,47 @@
"cc_binary(name = 'lib', data = ['a.txt'])",
"my_rule(name='my', dep = ':lib')");
NestedSet<Artifact> hiddenTopLevelArtifacts =
- getConfiguredTarget("//test/skylark:lib")
- .getProvider(OutputGroupProvider.class)
+ OutputGroupProvider.get(getConfiguredTarget("//test/skylark:lib"))
.getOutputGroup(OutputGroupProvider.HIDDEN_TOP_LEVEL);
ConfiguredTarget myTarget = getConfiguredTarget("//test/skylark:my");
SkylarkNestedSet result =
(SkylarkNestedSet) myTarget.getProvider(SkylarkProviders.class).getValue("result");
assertThat(result.getSet(Artifact.class)).containsExactlyElementsIn(hiddenTopLevelArtifacts);
- assertThat(myTarget.getProvider(OutputGroupProvider.class).getOutputGroup("my_group"))
+ assertThat(OutputGroupProvider.get(myTarget).getOutputGroup("my_group"))
.containsExactlyElementsIn(hiddenTopLevelArtifacts);
- assertThat(myTarget.getProvider(OutputGroupProvider.class).getOutputGroup("my_empty_group"))
+ assertThat(OutputGroupProvider.get(myTarget).getOutputGroup("my_empty_group"))
.isEmpty();
}
+
+ @Test
+ public void testOutputGroupsDeclaredProviderWithList() throws Exception {
+ scratch.file(
+ "test/skylark/extension.bzl",
+ "def _impl(ctx):",
+ " f = ctx.attr.dep[OutputGroupInfo]._hidden_top_level" + INTERNAL_SUFFIX,
+ " g = list(f)",
+ " return struct(result = f, ",
+ " providers = [OutputGroupInfo(my_group = g, my_empty_group = [])])",
+ "my_rule = rule(implementation = _impl,",
+ " attrs = { 'dep' : attr.label() })");
+ scratch.file(
+ "test/skylark/BUILD",
+ "load('/test/skylark/extension', 'my_rule')",
+ "cc_binary(name = 'lib', data = ['a.txt'])",
+ "my_rule(name='my', dep = ':lib')");
+ NestedSet<Artifact> hiddenTopLevelArtifacts =
+ OutputGroupProvider.get(getConfiguredTarget("//test/skylark:lib"))
+ .getOutputGroup(OutputGroupProvider.HIDDEN_TOP_LEVEL);
+ ConfiguredTarget myTarget = getConfiguredTarget("//test/skylark:my");
+ SkylarkNestedSet result =
+ (SkylarkNestedSet) myTarget.getProvider(SkylarkProviders.class).getValue("result");
+ assertThat(result.getSet(Artifact.class)).containsExactlyElementsIn(hiddenTopLevelArtifacts);
+ assertThat(OutputGroupProvider.get(myTarget).getOutputGroup("my_group"))
+ .containsExactlyElementsIn(hiddenTopLevelArtifacts);
+ assertThat(OutputGroupProvider.get(myTarget).getOutputGroup("my_empty_group"))
+ .isEmpty();
+ }
+
@Test
public void testStackTraceErrorInFunction() throws Exception {
runStackTraceTest(