From 614dc50056348f5cb8eff626c30b4fdf573f2253 Mon Sep 17 00:00:00 2001 From: gregce Date: Wed, 20 Dec 2017 17:24:46 -0800 Subject: 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 --- .../analysis/config/ConfigAwareAspectBuilder.java | 89 +++++++++++++++++++++ .../config/ConfigAwareRuleClassBuilder.java | 90 ++++++++++++++++++++++ .../build/lib/analysis/config/HostTransition.java | 5 ++ .../lib/analysis/constraints/EnvironmentRule.java | 2 + .../skylark/SkylarkRuleClassFunctions.java | 15 ++-- .../lib/bazel/rules/java/BazelJavaLibraryRule.java | 10 ++- .../build/lib/packages/AspectDefinition.java | 34 +++++--- .../devtools/build/lib/packages/Attribute.java | 19 ++++- .../lib/packages/ConfigurationFragmentPolicy.java | 85 ++++++++++---------- .../build/lib/packages/DependencyFilter.java | 3 +- .../devtools/build/lib/packages/RuleClass.java | 46 +++++++---- .../build/lib/packages/SkylarkDefinedAspect.java | 6 +- .../build/lib/rules/objc/J2ObjcAspect.java | 26 ++++--- 13 files changed, 335 insertions(+), 95 deletions(-) create mode 100644 src/main/java/com/google/devtools/build/lib/analysis/config/ConfigAwareAspectBuilder.java create mode 100644 src/main/java/com/google/devtools/build/lib/analysis/config/ConfigAwareRuleClassBuilder.java (limited to 'src/main/java') 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. + * + *

{@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. + * + *

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. + * + *

This is not the same as the aspect's configuration. The aspect's configuration is its + * target 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. + * + *

The value is inherited by subclasses. + */ + public ConfigAwareAspectBuilder requiresHostConfigurationFragments( + Class... 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. + * + *

This is not the same as the aspect's configuration. The aspect's configuration is its + * target 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. + * + *

In contrast to {@link #requiresHostConfigurationFragments(Class...)}, this method takes + * Skylark module names of fragments instead of their classes. + */ + public ConfigAwareAspectBuilder requiresHostConfigurationFragmentsBySkylarkModuleName( + Collection 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. + * + *

{@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. + * + *

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. + * + *

This is not the same as the rule's configuration. The rule's configuration is its + * target 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. + * + *

The value is inherited by subclasses. + */ + public ConfigAwareRuleClassBuilder requiresHostConfigurationFragments( + Class... 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. + * + *

This is not the same as the rule's configuration. The rule's configuration is its + * target 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. + * + *

In contrast to {@link #requiresHostConfigurationFragments(Class...)}, this method takes + * Skylark module names of fragments instead of their classes. + */ + public ConfigAwareRuleClassBuilder requiresHostConfigurationFragmentsBySkylarkModuleName( + Collection 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 @@ -21,6 +21,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) { 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 /*