aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java
diff options
context:
space:
mode:
authorGravatar gregce <gregce@google.com>2017-12-20 17:24:46 -0800
committerGravatar Copybara-Service <copybara-piper@google.com>2017-12-20 17:26:58 -0800
commit614dc50056348f5cb8eff626c30b4fdf573f2253 (patch)
treeeeafa4325ddd8d15ce84abecdac9fa090ce4f9b7 /src/main/java
parentdeb9c882fb6ecab1c27f28e5e145926d18e2a3d5 (diff)
Remove ConfigurationTransition.HOST references from lib.packages.
This removes the main barrier to making host transitions routine patch transitions. Today you signify a host transition by calling Attribute.Builder.cfg(ConfigurationTransition.HOST). Blaze's configuration machinery auto-converts this to HostTransition.INSTANCE, which is a patch transition. This change provides the groundwork for removing ConfigurationTransition.HOST and removing the special conversion logic. This also paves the way for better API support for multiple host configurations. Also change some cfg(HOST) rule references to cfg(HostTransition.INSTANCE). PiperOrigin-RevId: 179754619
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/com/google/devtools/build/lib/analysis/config/ConfigAwareAspectBuilder.java89
-rw-r--r--src/main/java/com/google/devtools/build/lib/analysis/config/ConfigAwareRuleClassBuilder.java90
-rw-r--r--src/main/java/com/google/devtools/build/lib/analysis/config/HostTransition.java5
-rw-r--r--src/main/java/com/google/devtools/build/lib/analysis/constraints/EnvironmentRule.java2
-rw-r--r--src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleClassFunctions.java15
-rw-r--r--src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaLibraryRule.java10
-rw-r--r--src/main/java/com/google/devtools/build/lib/packages/AspectDefinition.java34
-rw-r--r--src/main/java/com/google/devtools/build/lib/packages/Attribute.java19
-rw-r--r--src/main/java/com/google/devtools/build/lib/packages/ConfigurationFragmentPolicy.java85
-rw-r--r--src/main/java/com/google/devtools/build/lib/packages/DependencyFilter.java3
-rw-r--r--src/main/java/com/google/devtools/build/lib/packages/RuleClass.java46
-rw-r--r--src/main/java/com/google/devtools/build/lib/packages/SkylarkDefinedAspect.java6
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcAspect.java26
13 files changed, 335 insertions, 95 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/config/ConfigAwareAspectBuilder.java b/src/main/java/com/google/devtools/build/lib/analysis/config/ConfigAwareAspectBuilder.java
new file mode 100644
index 0000000000..0b6bb2a5a4
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/analysis/config/ConfigAwareAspectBuilder.java
@@ -0,0 +1,89 @@
+// Copyright 2017 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.devtools.build.lib.analysis.config;
+
+import com.google.devtools.build.lib.packages.AspectDefinition;
+import java.util.Collection;
+
+/**
+ * A wrapper for {@link AspectDefinition.Builder} that supports access to {@link
+ * com.google.devtools.build.lib.analysis} classes.
+ *
+ * <p>{@link AspectDefinition.Builder} is in {@link com.google.devtools.build.lib.packages}, so it
+ * can't reference analysis-time objects.
+ */
+public class ConfigAwareAspectBuilder {
+ private final AspectDefinition.Builder aspectBuilder;
+
+ /**
+ * Instantiates a builder wrapped around the given {@link AspectDefinition.Builder}.
+ */
+ private ConfigAwareAspectBuilder(AspectDefinition.Builder aspectBuilder) {
+ this.aspectBuilder = aspectBuilder;
+ }
+
+ /**
+ * Instantiates a builder wrapped around the given {@link AspectDefinition.Builder}.
+ */
+ public static ConfigAwareAspectBuilder of(AspectDefinition.Builder aspectBuilder) {
+ return new ConfigAwareAspectBuilder(aspectBuilder);
+ }
+
+ /**
+ * Returns the {@link AspectDefinition.Builder} this object wraps.
+ *
+ * <p>Call this when done with config-specific building to re-expose the builder methods in
+ * {@link AspectDefinition.Builder}
+ */
+ public AspectDefinition.Builder originalBuilder() {
+ return aspectBuilder;
+ }
+
+ /**
+ * Declares the fragments required by this aspect for the configuration of the host machine this
+ * aspect's actions execute on.
+ *
+ * <p>This is not the same as the aspect's configuration. The aspect's configuration is its
+ * <i>target</i> configuration, which determines the platform it builds outputs for. The actions
+ * created by this aspect run on a host machine, which is what the host configuration corresponds
+ * to.
+ *
+ * <p>The value is inherited by subclasses.
+ */
+ public ConfigAwareAspectBuilder requiresHostConfigurationFragments(
+ Class<? extends BuildConfiguration.Fragment>... configurationFragments) {
+ aspectBuilder.requiresConfigurationFragments(HostTransition.INSTANCE, configurationFragments);
+ return this;
+ }
+
+ /**
+ * Declares the fragments required by this aspect for the configuration of the host machine this
+ * aspect's actions execute on.
+ *
+ * <p>This is not the same as the aspect's configuration. The aspect's configuration is its
+ * <i>target</i> configuration, which determines the platform it builds outputs for. The actions
+ * created by this aspect run on a host machine, which is what the host configuration corresponds
+ * to.
+ *
+ * <p>In contrast to {@link #requiresHostConfigurationFragments(Class...)}, this method takes
+ * Skylark module names of fragments instead of their classes.
+ */
+ public ConfigAwareAspectBuilder requiresHostConfigurationFragmentsBySkylarkModuleName(
+ Collection<String> configurationFragmentNames) {
+ aspectBuilder.requiresConfigurationFragmentsBySkylarkModuleName(HostTransition.INSTANCE,
+ configurationFragmentNames);
+ return this;
+ }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/config/ConfigAwareRuleClassBuilder.java b/src/main/java/com/google/devtools/build/lib/analysis/config/ConfigAwareRuleClassBuilder.java
new file mode 100644
index 0000000000..bfa54147ea
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/analysis/config/ConfigAwareRuleClassBuilder.java
@@ -0,0 +1,90 @@
+// Copyright 2017 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.devtools.build.lib.analysis.config;
+
+import com.google.devtools.build.lib.packages.RuleClass;
+import java.util.Collection;
+
+/**
+ * A wrapper for {@link RuleClass.Builder} that supports access to {@link
+ * com.google.devtools.build.lib.analysis} classes.
+ *
+ * <p>{@link RuleClass.Builder} is in {@link com.google.devtools.build.lib.packages}, so it can't
+ * reference analysis-time objects.
+ */
+public class ConfigAwareRuleClassBuilder {
+ private final RuleClass.Builder ruleClassBuilder;
+
+ /**
+ * Instantiates a builder wrapped around the given {@link RuleClass.Builder}.
+ */
+ private ConfigAwareRuleClassBuilder(RuleClass.Builder ruleClassBuilder) {
+ this.ruleClassBuilder = ruleClassBuilder;
+ }
+
+ /**
+ * Instantiates a builder wrapped around the given {@link RuleClass.Builder}.
+ */
+ public static ConfigAwareRuleClassBuilder of(RuleClass.Builder ruleClassBuilder) {
+ return new ConfigAwareRuleClassBuilder(ruleClassBuilder);
+ }
+
+ /**
+ * Returns the {@link RuleClass.Builder} this object wraps.
+ *
+ * <p>Call this when done with config-specific building to re-expose the builder methods in
+ * {@link RuleClass.Builder}
+ */
+ public RuleClass.Builder originalBuilder() {
+ return ruleClassBuilder;
+ }
+
+ /**
+ * Declares the fragments required by this rule for the configuration of the host machine this
+ * rule's actions execute on.
+ *
+ * <p>This is not the same as the rule's configuration. The rule's configuration is its
+ * <i>target</i> configuration, which determines the platform it builds outputs for. The actions
+ * created by this rule run on a host machine, which is what the host configuration corresponds
+ * to.
+ *
+ * <p>The value is inherited by subclasses.
+ */
+ public ConfigAwareRuleClassBuilder requiresHostConfigurationFragments(
+ Class<? extends BuildConfiguration.Fragment>... configurationFragments) {
+ ruleClassBuilder.requiresConfigurationFragments(HostTransition.INSTANCE,
+ configurationFragments);
+ return this;
+ }
+
+ /**
+ * Declares the fragments required by this rule for the configuration of the host machine this
+ * rule's actions execute on.
+ *
+ * <p>This is not the same as the rule's configuration. The rule's configuration is its
+ * <i>target</i> configuration, which determines the platform it builds outputs for. The actions
+ * created by this rule run on a host machine, which is what the host configuration corresponds
+ * to.
+ *
+ * <p>In contrast to {@link #requiresHostConfigurationFragments(Class...)}, this method takes
+ * Skylark module names of fragments instead of their classes.
+ */
+ public ConfigAwareRuleClassBuilder requiresHostConfigurationFragmentsBySkylarkModuleName(
+ Collection<String> configurationFragmentNames) {
+ ruleClassBuilder.requiresConfigurationFragmentsBySkylarkModuleName(HostTransition.INSTANCE,
+ configurationFragmentNames);
+ return this;
+ }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/config/HostTransition.java b/src/main/java/com/google/devtools/build/lib/analysis/config/HostTransition.java
index e593cd7621..099c8fdf2f 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/config/HostTransition.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/config/HostTransition.java
@@ -22,6 +22,11 @@ public final class HostTransition implements PatchTransition {
private HostTransition() {}
@Override
+ public boolean isHostTransition() {
+ return true;
+ }
+
+ @Override
public BuildOptions apply(BuildOptions options) {
if (options.get(BuildConfiguration.Options.class).isHost) {
// If the input already comes from the host configuration, just return the existing values.
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/constraints/EnvironmentRule.java b/src/main/java/com/google/devtools/build/lib/analysis/constraints/EnvironmentRule.java
index 48a0182a25..0bfcbc55bb 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/constraints/EnvironmentRule.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/constraints/EnvironmentRule.java
@@ -20,6 +20,7 @@ import com.google.common.collect.ImmutableList;
import com.google.devtools.build.lib.analysis.BaseRuleClasses;
import com.google.devtools.build.lib.analysis.RuleDefinition;
import com.google.devtools.build.lib.analysis.RuleDefinitionEnvironment;
+import com.google.devtools.build.lib.analysis.config.HostTransition;
import com.google.devtools.build.lib.packages.BuildType;
import com.google.devtools.build.lib.packages.RuleClass;
import com.google.devtools.build.lib.syntax.Type;
@@ -36,6 +37,7 @@ public class EnvironmentRule implements RuleDefinition {
@Override
public RuleClass build(RuleClass.Builder builder, RuleDefinitionEnvironment env) {
return builder
+ .cfg(HostTransition.INSTANCE)
.override(attr("tags", Type.STRING_LIST)
// No need to show up in ":all", etc. target patterns.
.value(ImmutableList.of("manual"))
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleClassFunctions.java b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleClassFunctions.java
index 350e98d41c..1e7d5fe5dc 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleClassFunctions.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleClassFunctions.java
@@ -16,7 +16,6 @@ package com.google.devtools.build.lib.analysis.skylark;
import static com.google.devtools.build.lib.analysis.BaseRuleClasses.RUN_UNDER;
import static com.google.devtools.build.lib.packages.Attribute.ConfigurationTransition.DATA;
-import static com.google.devtools.build.lib.packages.Attribute.ConfigurationTransition.HOST;
import static com.google.devtools.build.lib.packages.Attribute.attr;
import static com.google.devtools.build.lib.packages.BuildType.LABEL;
import static com.google.devtools.build.lib.packages.BuildType.LABEL_LIST;
@@ -40,6 +39,8 @@ import com.google.devtools.build.lib.analysis.BaseRuleClasses;
import com.google.devtools.build.lib.analysis.DefaultInfo;
import com.google.devtools.build.lib.analysis.OutputGroupInfo;
import com.google.devtools.build.lib.analysis.TransitiveInfoCollection;
+import com.google.devtools.build.lib.analysis.config.ConfigAwareRuleClassBuilder;
+import com.google.devtools.build.lib.analysis.config.HostTransition;
import com.google.devtools.build.lib.analysis.skylark.SkylarkAttr.Descriptor;
import com.google.devtools.build.lib.analysis.test.TestConfiguration;
import com.google.devtools.build.lib.cmdline.Label;
@@ -184,19 +185,19 @@ public class SkylarkRuleClassFunctions {
// Input files for every test action
.add(
attr("$test_runtime", LABEL_LIST)
- .cfg(HOST)
+ .cfg(HostTransition.INSTANCE)
.value(
ImmutableList.of(
labelCache.getUnchecked(toolsRepository + "//tools/test:runtime"))))
// Input files for test actions collecting code coverage
.add(
attr("$coverage_support", LABEL)
- .cfg(HOST)
+ .cfg(HostTransition.INSTANCE)
.value(labelCache.getUnchecked("//tools/defaults:coverage_support")))
// Used in the one-per-build coverage report generation action.
.add(
attr("$coverage_report_generator", LABEL)
- .cfg(HOST)
+ .cfg(HostTransition.INSTANCE)
.value(labelCache.getUnchecked("//tools/defaults:coverage_report_generator"))
.singleArtifact())
.add(attr(":run_under", LABEL).cfg(DATA).value(RUN_UNDER))
@@ -546,8 +547,9 @@ public class SkylarkRuleClassFunctions {
builder.requiresConfigurationFragmentsBySkylarkModuleName(
fragments.getContents(String.class, "fragments"));
- builder.requiresHostConfigurationFragmentsBySkylarkModuleName(
- hostFragments.getContents(String.class, "host_fragments"));
+ ConfigAwareRuleClassBuilder.of(builder)
+ .requiresHostConfigurationFragmentsBySkylarkModuleName(
+ hostFragments.getContents(String.class, "host_fragments"));
builder.setConfiguredTargetFunction(implementation);
builder.setRuleDefinitionEnvironment(funcallEnv);
builder.addRequiredToolchains(collectToolchainLabels(toolchains, ast));
@@ -805,6 +807,7 @@ public class SkylarkRuleClassFunctions {
SkylarkAttr.getSkylarkProviderIdentifiers(providesArg, ast.getLocation()),
requiredParams.build(),
ImmutableSet.copyOf(fragments.getContents(String.class, "fragments")),
+ HostTransition.INSTANCE,
ImmutableSet.copyOf(hostFragments.getContents(String.class, "host_fragments")),
collectToolchainLabels(toolchains, ast),
funcallEnv);
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaLibraryRule.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaLibraryRule.java
index 270238f015..f302d345af 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaLibraryRule.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaLibraryRule.java
@@ -14,7 +14,6 @@
package com.google.devtools.build.lib.bazel.rules.java;
-import static com.google.devtools.build.lib.packages.Attribute.ConfigurationTransition.HOST;
import static com.google.devtools.build.lib.packages.Attribute.attr;
import static com.google.devtools.build.lib.packages.BuildType.LABEL_LIST;
import static com.google.devtools.build.lib.syntax.Type.BOOLEAN;
@@ -22,6 +21,8 @@ import static com.google.devtools.build.lib.syntax.Type.STRING_LIST;
import com.google.devtools.build.lib.analysis.RuleDefinition;
import com.google.devtools.build.lib.analysis.RuleDefinitionEnvironment;
+import com.google.devtools.build.lib.analysis.config.ConfigAwareRuleClassBuilder;
+import com.google.devtools.build.lib.analysis.config.HostTransition;
import com.google.devtools.build.lib.bazel.rules.java.BazelJavaRuleClasses.JavaRule;
import com.google.devtools.build.lib.packages.RuleClass;
import com.google.devtools.build.lib.packages.RuleClass.Builder;
@@ -40,9 +41,10 @@ public final class BazelJavaLibraryRule implements RuleDefinition {
@Override
public RuleClass build(Builder builder, final RuleDefinitionEnvironment env) {
- return builder
+ return ConfigAwareRuleClassBuilder.of(builder)
+ .requiresHostConfigurationFragments(Jvm.class) // For getting the host Java executable.
+ .originalBuilder()
.requiresConfigurationFragments(JavaConfiguration.class, CppConfiguration.class)
- .requiresHostConfigurationFragments(Jvm.class) // For BaseJavaCompilationHelper
/* <!-- #BLAZE_RULE(java_library).IMPLICIT_OUTPUTS -->
<ul>
<li><code>lib<var>name</var>.jar</code>: A Java archive containing the class files.</li>
@@ -149,7 +151,7 @@ public final class BazelJavaLibraryRule implements RuleDefinition {
<!-- #END_BLAZE_RULE.ATTRIBUTE --> */
.add(
attr("exported_plugins", LABEL_LIST)
- .cfg(HOST)
+ .cfg(HostTransition.INSTANCE)
.allowedRuleClasses("java_plugin")
.allowedFileTypes())
.advertiseProvider(JavaSourceInfoProvider.class)
diff --git a/src/main/java/com/google/devtools/build/lib/packages/AspectDefinition.java b/src/main/java/com/google/devtools/build/lib/packages/AspectDefinition.java
index eea440e521..773001e004 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/AspectDefinition.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/AspectDefinition.java
@@ -24,6 +24,7 @@ import com.google.common.collect.Multimap;
import com.google.common.collect.SetMultimap;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
+import com.google.devtools.build.lib.packages.Attribute.Transition;
import com.google.devtools.build.lib.packages.ConfigurationFragmentPolicy.MissingFragmentPolicy;
import com.google.devtools.build.lib.syntax.Type;
import com.google.devtools.build.lib.syntax.Type.LabelClass;
@@ -418,13 +419,19 @@ public final class AspectDefinition {
/**
* Declares that the implementation of the associated aspect definition requires the given
- * fragments to be present in the host configuration.
+ * fragments to be present in the given configuration that isn't the aspect's configuration but
+ * is also readable by the aspect.
+ *
+ * <p>You probably don't want to use this, because aspects generally shouldn't read
+ * configurations other than their own. If you want to declare host config fragments, see
+ * {@link com.google.devtools.build.lib.analysis.config.ConfigAwareAspectBuilder}.
*
* <p>The value is inherited by subclasses.
*/
- public Builder requiresHostConfigurationFragments(Class<?>... configurationFragments) {
- configurationFragmentPolicy
- .requiresHostConfigurationFragments(ImmutableSet.copyOf(configurationFragments));
+ public Builder requiresConfigurationFragments(Transition transition,
+ Class<?>... configurationFragments) {
+ configurationFragmentPolicy.requiresConfigurationFragments(transition,
+ ImmutableSet.copyOf(configurationFragments));
return this;
}
@@ -443,16 +450,21 @@ public final class AspectDefinition {
}
/**
- * Declares the configuration fragments that are required by this rule for the host
- * configuration.
+ * Declares that the implementation of the associated aspect definition requires the given
+ * fragments to be present in the given configuration that isn't the aspect's configuration but
+ * is also readable by the aspect.
+ *
+ * <p>In contrast to {@link #requiresConfigurationFragments(Transition, Class...)}, this method
+ * takes the Skylark module names of fragments instead of their classes.
*
- * <p>In contrast to {@link #requiresHostConfigurationFragments(Class...)}, this method takes
- * the Skylark module names of fragments instead of their classes.
+ * <p>You probably don't want to use this, because aspects generally shouldn't read
+ * configurations other than their own. If you want to declare host config fragments, see
+ * {@link com.google.devtools.build.lib.analysis.config.ConfigAwareAspectBuilder}.
*/
- public Builder requiresHostConfigurationFragmentsBySkylarkModuleName(
+ public Builder requiresConfigurationFragmentsBySkylarkModuleName(Transition transition,
Collection<String> configurationFragmentNames) {
- configurationFragmentPolicy
- .requiresHostConfigurationFragmentsBySkylarkModuleName(configurationFragmentNames);
+ configurationFragmentPolicy.requiresConfigurationFragmentsBySkylarkModuleName(transition,
+ configurationFragmentNames);
return this;
}
diff --git a/src/main/java/com/google/devtools/build/lib/packages/Attribute.java b/src/main/java/com/google/devtools/build/lib/packages/Attribute.java
index 9877ea4054..d0ed2195f3 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/Attribute.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/Attribute.java
@@ -150,6 +150,12 @@ public final class Attribute implements Comparable<Attribute> {
* A configuration transition.
*/
public interface Transition {
+ /**
+ * Does this transition switch to a "host" configuration?
+ */
+ default boolean isHostTransition() {
+ return false;
+ }
}
/**
@@ -171,13 +177,22 @@ public final class Attribute implements Comparable<Attribute> {
/**
* Declaration how the configuration should change when following a label or label list attribute.
+ *
+ * <p>Do not add to this. Use {@link
+ * com.google.devtools.build.lib.analysis.config.PatchTransition} or {@link SplitTransition}
+ * instead.
*/
public enum ConfigurationTransition implements Transition {
/** No transition, i.e., the same configuration as the current. */
NONE,
/** Transition to the host configuration. */
- HOST,
+ HOST {
+ @Override
+ public boolean isHostTransition() {
+ return true;
+ }
+ },
/** Transition to a null configuration (applies to, e.g., input files). */
NULL,
@@ -1860,7 +1875,7 @@ public final class Attribute implements Comparable<Attribute> {
if (isLateBound(name)) {
LateBoundDefault<?, ?> lateBoundDefault = (LateBoundDefault<?, ?>) defaultValue;
Preconditions.checkArgument(!lateBoundDefault.useHostConfiguration()
- || (configTransition == ConfigurationTransition.HOST),
+ || (configTransition.isHostTransition()),
"a late bound default value using the host configuration must use the host transition");
}
diff --git a/src/main/java/com/google/devtools/build/lib/packages/ConfigurationFragmentPolicy.java b/src/main/java/com/google/devtools/build/lib/packages/ConfigurationFragmentPolicy.java
index c75c01b088..793ec84eb2 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/ConfigurationFragmentPolicy.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/ConfigurationFragmentPolicy.java
@@ -13,14 +13,16 @@
// limitations under the License.
package com.google.devtools.build.lib.packages;
+import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSetMultimap;
import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.SetMultimap;
import com.google.devtools.build.lib.packages.Attribute.ConfigurationTransition;
+import com.google.devtools.build.lib.packages.Attribute.Transition;
import com.google.devtools.build.lib.skylarkinterface.SkylarkModule;
-
import java.util.Collection;
+import java.util.Map;
import java.util.Set;
/**
@@ -64,13 +66,13 @@ public final class ConfigurationFragmentPolicy {
* Sets of configuration fragment classes required by this rule, a set for each configuration.
* Duplicate entries will automatically be ignored by the SetMultimap.
*/
- private final SetMultimap<ConfigurationTransition, Class<?>> requiredConfigurationFragments
+ private final SetMultimap<Transition, Class<?>> requiredConfigurationFragments
= LinkedHashMultimap.create();
/**
* Sets of configuration fragment names required by this rule, a set for each configuration.
* Duplicate entries will automatically be ignored by the SetMultimap.
*/
- private final SetMultimap<ConfigurationTransition, String> requiredConfigurationFragmentNames
+ private final SetMultimap<Transition, String> requiredConfigurationFragmentNames
= LinkedHashMultimap.create();
private MissingFragmentPolicy missingFragmentPolicy = MissingFragmentPolicy.FAIL_ANALYSIS;
@@ -87,25 +89,19 @@ public final class ConfigurationFragmentPolicy {
/**
* Declares that the implementation of the associated rule class requires the given
- * fragments to be present in this rule's host configuration only.
- *
- * <p>The value is inherited by subclasses.
- */
- public Builder requiresHostConfigurationFragments(Collection<Class<?>> configurationFragments) {
- requiresConfigurationFragments(ConfigurationTransition.HOST, configurationFragments);
- return this;
- }
-
- /**
- * Declares that the implementation of the associated rule class requires the given
* fragments to be present in the specified configuration. Valid transition values are
* HOST for the host configuration and NONE for the target configuration.
*
* <p>The value is inherited by subclasses.
*/
- private void requiresConfigurationFragments(ConfigurationTransition transition,
+ public Builder requiresConfigurationFragments(Attribute.Transition transition,
Collection<Class<?>> configurationFragments) {
+ // We can relax this assumption if needed. But it's already sketchy to let a rule see more
+ // than its own configuration. So we don't want to casually proliferate this pattern.
+ Preconditions.checkArgument(
+ transition == Attribute.ConfigurationTransition.NONE || transition.isHostTransition());
requiredConfigurationFragments.putAll(transition, configurationFragments);
+ return this;
}
/**
@@ -120,25 +116,9 @@ public final class ConfigurationFragmentPolicy {
*/
public Builder requiresConfigurationFragmentsBySkylarkModuleName(
Collection<String> configurationFragmentNames) {
- requiresConfigurationFragmentsBySkylarkModuleName(
- ConfigurationTransition.NONE, configurationFragmentNames);
- return this;
- }
- /**
- * Declares that the implementation of the associated rule class requires the given
- * fragments to be present in this rule's host configuration only.
- *
- * <p>In contrast to {@link #requiresHostConfigurationFragments(Collection)}, this method takes
- * the names of fragments (as determined by {@link SkylarkModule.Resolver}) instead of their
- * classes.
- *
- * <p>The value is inherited by subclasses.
- */
- public Builder requiresHostConfigurationFragmentsBySkylarkModuleName(
- Collection<String> configurationFragmentNames) {
requiresConfigurationFragmentsBySkylarkModuleName(
- ConfigurationTransition.HOST, configurationFragmentNames);
+ Attribute.ConfigurationTransition.NONE, configurationFragmentNames);
return this;
}
@@ -147,13 +127,19 @@ public final class ConfigurationFragmentPolicy {
* configuration. Valid transition values are HOST for the host configuration and NONE for
* the target configuration.
*
- * <p>In contrast to {@link #requiresConfigurationFragments(Collection)}, this method takes the
- * names of fragments (as determined by {@link SkylarkModule.Resolver}) instead of their
+ * <p>In contrast to {@link #requiresConfigurationFragments(Transition,
+ * Collection)}, this method takes the names of fragments (as determined by
+ * {@link SkylarkModule.Resolver}) instead of their
* classes.
*/
- private void requiresConfigurationFragmentsBySkylarkModuleName(
- ConfigurationTransition transition, Collection<String> configurationFragmentNames) {
+ public Builder requiresConfigurationFragmentsBySkylarkModuleName(Transition transition,
+ Collection<String> configurationFragmentNames) {
+ // We can relax this assumption if needed. But it's already sketchy to let a rule see more
+ // than its own configuration. So we don't want to casually proliferate this pattern.
+ Preconditions.checkArgument(
+ transition == ConfigurationTransition.NONE || transition.isHostTransition());
requiredConfigurationFragmentNames.putAll(transition, configurationFragmentNames);
+ return this;
}
/**
@@ -188,14 +174,14 @@ public final class ConfigurationFragmentPolicy {
* A dictionary that maps configurations (NONE for target configuration, HOST for host
* configuration) to required configuration fragments.
*/
- private final ImmutableSetMultimap<ConfigurationTransition, Class<?>>
+ private final ImmutableSetMultimap<Transition, Class<?>>
requiredConfigurationFragments;
/**
* A dictionary that maps configurations (NONE for target configuration, HOST for host
* configuration) to lists of Skylark module names of required configuration fragments.
*/
- private final ImmutableSetMultimap<ConfigurationTransition, String>
+ private final ImmutableSetMultimap<Transition, String>
requiredConfigurationFragmentNames;
/**
@@ -204,8 +190,8 @@ public final class ConfigurationFragmentPolicy {
private final MissingFragmentPolicy missingFragmentPolicy;
private ConfigurationFragmentPolicy(
- ImmutableSetMultimap<ConfigurationTransition, Class<?>> requiredConfigurationFragments,
- ImmutableSetMultimap<ConfigurationTransition, String> requiredConfigurationFragmentNames,
+ ImmutableSetMultimap<Transition, Class<?>> requiredConfigurationFragments,
+ ImmutableSetMultimap<Transition, String> requiredConfigurationFragmentNames,
MissingFragmentPolicy missingFragmentPolicy) {
this.requiredConfigurationFragments = requiredConfigurationFragments;
this.requiredConfigurationFragmentNames = requiredConfigurationFragmentNames;
@@ -228,7 +214,7 @@ public final class ConfigurationFragmentPolicy {
* specified in the same configuration that was passed.
*/
public boolean isLegalConfigurationFragment(
- Class<?> configurationFragment, ConfigurationTransition config) {
+ Class<?> configurationFragment, Transition config) {
return requiredConfigurationFragments.containsValue(configurationFragment)
|| hasLegalFragmentName(configurationFragment, config);
}
@@ -247,9 +233,20 @@ public final class ConfigurationFragmentPolicy {
* specified configuration (target or host).
*/
private boolean hasLegalFragmentName(
- Class<?> configurationFragment, ConfigurationTransition config) {
- return requiredConfigurationFragmentNames.containsEntry(
- config, SkylarkModule.Resolver.resolveName(configurationFragment));
+ Class<?> configurationFragment, Transition transition) {
+ String name = SkylarkModule.Resolver.resolveName(configurationFragment);
+ if (requiredConfigurationFragmentNames.containsEntry(transition, name)) {
+ return true;
+ } else if (transition == ConfigurationTransition.HOST) {
+ // We can get rid of this check when we remove ConfigurationTransition.HOST. This essentially
+ // makes ConfigurationTransition.HOST and HostTransition.INSTANCE interchangeable.
+ for (Map.Entry<Transition, String> entry : requiredConfigurationFragmentNames.entries()) {
+ if (entry.getKey().isHostTransition() && entry.getValue().equals(name)) {
+ return true;
+ }
+ }
+ }
+ return false;
}
/**
diff --git a/src/main/java/com/google/devtools/build/lib/packages/DependencyFilter.java b/src/main/java/com/google/devtools/build/lib/packages/DependencyFilter.java
index 88fe6d4157..f3d4971647 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/DependencyFilter.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/DependencyFilter.java
@@ -13,7 +13,6 @@
// limitations under the License.
package com.google.devtools.build.lib.packages;
-import com.google.devtools.build.lib.packages.Attribute.ConfigurationTransition;
import com.google.devtools.build.lib.packages.DependencyFilter.AttributeInfoProvider;
import com.google.devtools.build.lib.syntax.Type.LabelClass;
import com.google.devtools.build.lib.util.BinaryPredicate;
@@ -44,7 +43,7 @@ public abstract class DependencyFilter
return true;
}
- return attribute.getConfigurationTransition() != ConfigurationTransition.HOST;
+ return !attribute.getConfigurationTransition().isHostTransition();
}
};
/** Dependency predicate that excludes implicit dependencies */
diff --git a/src/main/java/com/google/devtools/build/lib/packages/RuleClass.java b/src/main/java/com/google/devtools/build/lib/packages/RuleClass.java
index 273745bf41..e76339dc7b 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/RuleClass.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/RuleClass.java
@@ -14,7 +14,6 @@
package com.google.devtools.build.lib.packages;
-import static com.google.devtools.build.lib.packages.Attribute.ConfigurationTransition.HOST;
import static com.google.devtools.build.lib.packages.Attribute.attr;
import static com.google.devtools.build.lib.packages.BuildType.LABEL_LIST;
import static com.google.devtools.build.lib.syntax.Type.BOOLEAN;
@@ -708,12 +707,19 @@ public class RuleClass {
/**
* Declares that the implementation of the associated rule class requires the given
- * fragments to be present in the host configuration.
+ * fragments to be present in the given configuration that isn't the rule's configuration but
+ * is also readable by the rule.
+ *
+ * <p>You probably don't want to use this, because rules generally shouldn't read configurations
+ * other than their own. If you want to declare host config fragments, see
+ * {@link com.google.devtools.build.lib.analysis.config.ConfigAwareRuleClassBuilder}.
*
* <p>The value is inherited by subclasses.
*/
- public Builder requiresHostConfigurationFragments(Class<?>... configurationFragments) {
- configurationFragmentPolicy.requiresHostConfigurationFragments(
+ public Builder requiresConfigurationFragments(Transition transition,
+ Class<?>... configurationFragments) {
+ configurationFragmentPolicy.requiresConfigurationFragments(
+ transition,
ImmutableSet.<Class<?>>copyOf(configurationFragments));
return this;
}
@@ -736,13 +742,25 @@ public class RuleClass {
* Declares the configuration fragments that are required by this rule for the host
* configuration.
*
- * <p>In contrast to {@link #requiresHostConfigurationFragments(Class...)}, this method takes
- * Skylark module names of fragments instead of their classes.
*/
- public Builder requiresHostConfigurationFragmentsBySkylarkModuleName(
+ /**
+ * Declares that the implementation of the associated rule class requires the given
+ * fragments to be present in the given configuration that isn't the rule's configuration but
+ * is also readable by the rule.
+ *
+ * <p>In contrast to {@link #requiresConfigurationFragments(Transition, Class...)}, this method
+ * takes Skylark module names of fragments instead of their classes.
+ * *
+ * <p>You probably don't want to use this, because rules generally shouldn't read configurations
+ * other than their own. If you want to declare host config fragments, see
+ * {@link com.google.devtools.build.lib.analysis.config.ConfigAwareRuleClassBuilder}.
+ *
+ * <p>The value is inherited by subclasses.
+ */
+ public Builder requiresConfigurationFragmentsBySkylarkModuleName(Transition transition,
Collection<String> configurationFragmentNames) {
- configurationFragmentPolicy
- .requiresHostConfigurationFragmentsBySkylarkModuleName(configurationFragmentNames);
+ configurationFragmentPolicy.requiresConfigurationFragmentsBySkylarkModuleName(transition,
+ configurationFragmentNames);
return this;
}
@@ -1033,8 +1051,9 @@ public class RuleClass {
* {@link com.google.devtools.build.lib.analysis.constraints.ConstraintSemantics} for details.
*/
public <TYPE> Builder compatibleWith(Label... environments) {
- add(attr(DEFAULT_COMPATIBLE_ENVIRONMENT_ATTR, LABEL_LIST).cfg(HOST)
- .value(ImmutableList.copyOf(environments)));
+ add(
+ attr(DEFAULT_COMPATIBLE_ENVIRONMENT_ATTR, LABEL_LIST)
+ .value(ImmutableList.copyOf(environments)));
return this;
}
@@ -1049,9 +1068,10 @@ public class RuleClass {
public <TYPE> Builder restrictedTo(Label firstEnvironment, Label... otherEnvironments) {
ImmutableList<Label> environments = ImmutableList.<Label>builder().add(firstEnvironment)
.add(otherEnvironments).build();
- add(attr(DEFAULT_RESTRICTED_ENVIRONMENT_ATTR, LABEL_LIST).cfg(HOST).value(environments));
+ add(
+ attr(DEFAULT_RESTRICTED_ENVIRONMENT_ATTR, LABEL_LIST)
+ .value(environments));
return this;
-
}
/**
diff --git a/src/main/java/com/google/devtools/build/lib/packages/SkylarkDefinedAspect.java b/src/main/java/com/google/devtools/build/lib/packages/SkylarkDefinedAspect.java
index 85aea03880..15851545ad 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/SkylarkDefinedAspect.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/SkylarkDefinedAspect.java
@@ -37,6 +37,7 @@ public class SkylarkDefinedAspect implements SkylarkExportable, SkylarkAspect {
private final ImmutableSet<SkylarkProviderIdentifier> provides;
private final ImmutableSet<String> paramAttributes;
private final ImmutableSet<String> fragments;
+ private final Attribute.Transition hostTransition;
private final ImmutableSet<String> hostFragments;
private final ImmutableList<Label> requiredToolchains;
@@ -51,6 +52,8 @@ public class SkylarkDefinedAspect implements SkylarkExportable, SkylarkAspect {
ImmutableSet<SkylarkProviderIdentifier> provides,
ImmutableSet<String> paramAttributes,
ImmutableSet<String> fragments,
+ // The host transition is in lib.analysis, so we can't reference it directly here.
+ Attribute.Transition hostTransition,
ImmutableSet<String> hostFragments,
ImmutableList<Label> requiredToolchains,
Environment funcallEnv) {
@@ -61,6 +64,7 @@ public class SkylarkDefinedAspect implements SkylarkExportable, SkylarkAspect {
this.provides = provides;
this.paramAttributes = paramAttributes;
this.fragments = fragments;
+ this.hostTransition = hostTransition;
this.hostFragments = hostFragments;
this.requiredToolchains = requiredToolchains;
this.funcallEnv = funcallEnv;
@@ -149,7 +153,7 @@ public class SkylarkDefinedAspect implements SkylarkExportable, SkylarkAspect {
}
builder.advertiseProvider(advertisedSkylarkProviders.build());
builder.requiresConfigurationFragmentsBySkylarkModuleName(fragments);
- builder.requiresHostConfigurationFragmentsBySkylarkModuleName(hostFragments);
+ builder.requiresConfigurationFragmentsBySkylarkModuleName(hostTransition, hostFragments);
builder.addRequiredToolchains(requiredToolchains);
return builder.build();
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcAspect.java b/src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcAspect.java
index 5b508c2366..7811b01c51 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcAspect.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcAspect.java
@@ -14,7 +14,6 @@
package com.google.devtools.build.lib.rules.objc;
-import static com.google.devtools.build.lib.packages.Attribute.ConfigurationTransition.HOST;
import static com.google.devtools.build.lib.packages.Attribute.attr;
import static com.google.devtools.build.lib.packages.BuildType.LABEL;
import static java.nio.charset.StandardCharsets.ISO_8859_1;
@@ -37,6 +36,8 @@ import com.google.devtools.build.lib.analysis.actions.CustomCommandLine.VectorAr
import com.google.devtools.build.lib.analysis.actions.ParamFileInfo;
import com.google.devtools.build.lib.analysis.actions.ParameterFileWriteAction;
import com.google.devtools.build.lib.analysis.actions.SpawnAction;
+import com.google.devtools.build.lib.analysis.config.ConfigAwareAspectBuilder;
+import com.google.devtools.build.lib.analysis.config.HostTransition;
import com.google.devtools.build.lib.analysis.configuredtargets.RuleConfiguredTarget.Mode;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
@@ -114,7 +115,7 @@ public class J2ObjcAspect extends NativeAspectClass implements ConfiguredAspectF
protected AspectDefinition.Builder addAdditionalAttributes(AspectDefinition.Builder builder) {
return builder.add(
attr("$j2objc_plugin", LABEL)
- .cfg(HOST)
+ .cfg(HostTransition.INSTANCE)
.exec()
.value(
Label.parseAbsoluteUnchecked(
@@ -133,7 +134,9 @@ public class J2ObjcAspect extends NativeAspectClass implements ConfiguredAspectF
@Override
public AspectDefinition getDefinition(AspectParameters aspectParameters) {
- return addAdditionalAttributes(new AspectDefinition.Builder(this))
+ return ConfigAwareAspectBuilder.of(addAdditionalAttributes(new AspectDefinition.Builder(this)))
+ .requiresHostConfigurationFragments(Jvm.class)
+ .originalBuilder()
.propagateAlongAttribute("deps")
.propagateAlongAttribute("exports")
.propagateAlongAttribute("runtime_deps")
@@ -145,10 +148,9 @@ public class J2ObjcAspect extends NativeAspectClass implements ConfiguredAspectF
J2ObjcConfiguration.class,
ObjcConfiguration.class,
ProtoConfiguration.class)
- .requiresHostConfigurationFragments(Jvm.class)
.add(
attr("$j2objc", LABEL)
- .cfg(HOST)
+ .cfg(HostTransition.INSTANCE)
.exec()
.value(
Label.parseAbsoluteUnchecked(
@@ -156,7 +158,7 @@ public class J2ObjcAspect extends NativeAspectClass implements ConfiguredAspectF
.add(
attr("$j2objc_wrapper", LABEL)
.allowedFileTypes(FileType.of(".py"))
- .cfg(HOST)
+ .cfg(HostTransition.INSTANCE)
.exec()
.singleArtifact()
.value(
@@ -165,7 +167,7 @@ public class J2ObjcAspect extends NativeAspectClass implements ConfiguredAspectF
.add(
attr("$j2objc_header_map", LABEL)
.allowedFileTypes(FileType.of(".py"))
- .cfg(HOST)
+ .cfg(HostTransition.INSTANCE)
.exec()
.singleArtifact()
.value(
@@ -173,11 +175,11 @@ public class J2ObjcAspect extends NativeAspectClass implements ConfiguredAspectF
toolsRepository + "//tools/j2objc:j2objc_header_map")))
.add(
attr("$jre_emul_jar", LABEL)
- .cfg(HOST)
+ .cfg(HostTransition.INSTANCE)
.value(
Label.parseAbsoluteUnchecked(
toolsRepository + "//third_party/java/j2objc:jre_emul.jar")))
- .add(attr(":dead_code_report", LABEL).cfg(HOST).value(DEAD_CODE_REPORT))
+ .add(attr(":dead_code_report", LABEL).cfg(HostTransition.INSTANCE).value(DEAD_CODE_REPORT))
.add(
attr("$jre_lib", LABEL)
.value(
@@ -190,12 +192,12 @@ public class J2ObjcAspect extends NativeAspectClass implements ConfiguredAspectF
toolsRepository + "//third_party/java/j2objc:proto_runtime")))
.add(
attr("$xcrunwrapper", LABEL)
- .cfg(HOST)
+ .cfg(HostTransition.INSTANCE)
.exec()
.value(Label.parseAbsoluteUnchecked(toolsRepository + "//tools/objc:xcrunwrapper")))
.add(
attr(ObjcRuleClasses.LIBTOOL_ATTRIBUTE, LABEL)
- .cfg(HOST)
+ .cfg(HostTransition.INSTANCE)
.exec()
.value(Label.parseAbsoluteUnchecked(toolsRepository + "//tools/objc:libtool")))
.add(
@@ -206,7 +208,7 @@ public class J2ObjcAspect extends NativeAspectClass implements ConfiguredAspectF
.value(AppleToolchain.getXcodeConfigLabel(toolsRepository)))
.add(
attr("$zipper", LABEL)
- .cfg(HOST)
+ .cfg(HostTransition.INSTANCE)
.exec()
.value(Label.parseAbsoluteUnchecked(toolsRepository + "//tools/zip:zipper")))
.add(