diff options
Diffstat (limited to 'src/main/java')
27 files changed, 583 insertions, 685 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/BUILD b/src/main/java/com/google/devtools/build/lib/BUILD index ddadda214f..6bc24fa7fc 100644 --- a/src/main/java/com/google/devtools/build/lib/BUILD +++ b/src/main/java/com/google/devtools/build/lib/BUILD @@ -513,6 +513,7 @@ java_library( "//src/main/java/com/google/devtools/build/lib/actions", "//src/main/java/com/google/devtools/build/lib/buildeventstream", "//src/main/java/com/google/devtools/build/lib/buildeventstream/proto:build_event_stream_java_proto", + "//src/main/java/com/google/devtools/build/lib/cmdline", "//src/main/java/com/google/devtools/build/lib/collect", "//src/main/java/com/google/devtools/build/lib/collect/nestedset", "//src/main/java/com/google/devtools/build/lib/concurrent", diff --git a/src/main/java/com/google/devtools/build/lib/analysis/BaseRuleClasses.java b/src/main/java/com/google/devtools/build/lib/analysis/BaseRuleClasses.java index f52d66f209..8a8e815ad2 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/BaseRuleClasses.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/BaseRuleClasses.java @@ -40,11 +40,9 @@ import com.google.devtools.build.lib.analysis.constraints.EnvironmentRule; import com.google.devtools.build.lib.analysis.test.TestConfiguration; import com.google.devtools.build.lib.cmdline.Label; import com.google.devtools.build.lib.packages.Attribute; -import com.google.devtools.build.lib.packages.Attribute.LateBoundLabel; -import com.google.devtools.build.lib.packages.Attribute.LateBoundLabelList; +import com.google.devtools.build.lib.packages.Attribute.LateBoundDefault; import com.google.devtools.build.lib.packages.Attribute.Transition; import com.google.devtools.build.lib.packages.AttributeMap; -import com.google.devtools.build.lib.packages.Rule; import com.google.devtools.build.lib.packages.RuleClass; import com.google.devtools.build.lib.packages.RuleClass.Builder; import com.google.devtools.build.lib.packages.RuleClass.Builder.RuleClassType; @@ -73,35 +71,32 @@ public class BaseRuleClasses { } }; + // TODO(b/65746853): provide a way to do this without passing the entire configuration /** * Implementation for the :action_listener attribute. + * + * <p>action_listeners are special rules; they tell the build system to add extra_actions to + * existing rules. As such they need an edge to every ConfiguredTarget with the limitation that + * they only run on the target configuration and should not operate on action_listeners and + * extra_actions themselves (to avoid cycles). */ @VisibleForTesting - static final LateBoundLabelList<BuildConfiguration> ACTION_LISTENER = - new LateBoundLabelList<BuildConfiguration>() { - @Override - public List<Label> resolve(Rule rule, AttributeMap attributes, - BuildConfiguration configuration) { - // action_listeners are special rules; they tell the build system to add extra_actions to - // existing rules. As such they need an edge to every ConfiguredTarget with the limitation - // that they only run on the target configuration and should not operate on action_listeners - // and extra_actions themselves (to avoid cycles). - return configuration.getActionListeners(); - } - }; + static final LateBoundDefault<?, List<Label>> ACTION_LISTENER = + LateBoundDefault.fromTargetConfiguration( + BuildConfiguration.class, + ImmutableList.of(), + (rule, attributes, configuration) -> configuration.getActionListeners()); - /** - * Implementation for the :run_under attribute. - */ - public static final LateBoundLabel<BuildConfiguration> RUN_UNDER = - new LateBoundLabel<BuildConfiguration>() { - @Override - public Label resolve(Rule rule, AttributeMap attributes, - BuildConfiguration configuration) { - RunUnder runUnder = configuration.getRunUnder(); - return runUnder == null ? null : runUnder.getLabel(); - } - }; + // TODO(b/65746853): provide a way to do this without passing the entire configuration + /** Implementation for the :run_under attribute. */ + public static final LateBoundDefault<?, Label> RUN_UNDER = + LateBoundDefault.fromTargetConfiguration( + BuildConfiguration.class, + null, + (rule, attributes, configuration) -> { + RunUnder runUnder = configuration.getRunUnder(); + return runUnder != null ? runUnder.getLabel() : null; + }); /** * A base rule for all test rules. diff --git a/src/main/java/com/google/devtools/build/lib/analysis/DependencyResolver.java b/src/main/java/com/google/devtools/build/lib/analysis/DependencyResolver.java index 4997a895f8..855c985486 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/DependencyResolver.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/DependencyResolver.java @@ -13,6 +13,7 @@ // limitations under the License. package com.google.devtools.build.lib.analysis; +import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; @@ -367,9 +368,7 @@ public abstract class DependencyResolver { continue; } - @SuppressWarnings("unchecked") - LateBoundDefault<BuildConfiguration> lateBoundDefault = - (LateBoundDefault<BuildConfiguration>) attribute.getLateBoundDefault(); + LateBoundDefault<?, ?> lateBoundDefault = attribute.getLateBoundDefault(); Collection<BuildOptions> splitOptions = getSplitOptions(depResolver.rule, attribute, ruleConfig); @@ -452,20 +451,8 @@ public abstract class DependencyResolver { throws EvalException, InterruptedException { Preconditions.checkArgument(attribute.isLateBound()); - @SuppressWarnings("unchecked") - LateBoundDefault<BuildConfiguration> lateBoundDefault = - (LateBoundDefault<BuildConfiguration>) attribute.getLateBoundDefault(); - - // TODO(bazel-team): This might be too expensive - can we cache this somehow? - if (!lateBoundDefault.getRequiredConfigurationFragments().isEmpty()) { - if (!config.hasAllFragments(lateBoundDefault.getRequiredConfigurationFragments())) { - return ImmutableList.<Label>of(); - } - } - - // TODO(bazel-team): We should check if the implementation tries to access an undeclared - // fragment. - Object actualValue = lateBoundDefault.resolve(rule, attributeMap, config); + Object actualValue = + resolveLateBoundDefault(attribute.getLateBoundDefault(), rule, attributeMap, config); if (EvalUtils.isNullOrNone(actualValue)) { return ImmutableList.<Label>of(); } @@ -495,6 +482,29 @@ public abstract class DependencyResolver { } } + @VisibleForTesting(/* used to test LateBoundDefaults' default values */ ) + public static <FragmentT, ValueT> ValueT resolveLateBoundDefault( + LateBoundDefault<FragmentT, ValueT> lateBoundDefault, + Rule rule, + AttributeMap attributeMap, + BuildConfiguration config) { + Class<FragmentT> fragmentClass = lateBoundDefault.getFragmentClass(); + // TODO(b/65746853): remove this when nothing uses it anymore + if (BuildConfiguration.class.equals(fragmentClass)) { + return lateBoundDefault.resolve(rule, attributeMap, fragmentClass.cast(config)); + } + if (Void.class.equals(fragmentClass)) { + return lateBoundDefault.resolve(rule, attributeMap, null); + } + FragmentT fragment = + fragmentClass.cast( + config.getFragment((Class<? extends BuildConfiguration.Fragment>) fragmentClass)); + if (fragment == null) { + return null; + } + return lateBoundDefault.resolve(rule, attributeMap, fragment); + } + /** * Adds new dependencies to the given rule under the given attribute name * diff --git a/src/main/java/com/google/devtools/build/lib/analysis/config/DefaultsPackage.java b/src/main/java/com/google/devtools/build/lib/analysis/config/DefaultsPackage.java index 8ddadf130f..07d8c755b6 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/config/DefaultsPackage.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/config/DefaultsPackage.java @@ -21,7 +21,6 @@ import com.google.devtools.build.lib.cmdline.Label; import com.google.devtools.build.lib.cmdline.LabelSyntaxException; import com.google.devtools.build.lib.runtime.proto.InvocationPolicyOuterClass.InvocationPolicy; import com.google.devtools.build.lib.util.Preconditions; - import java.util.Locale; import java.util.Map; import java.util.Set; @@ -29,52 +28,41 @@ import java.util.Set; /** * A helper class to compute and inject a defaults package into the package cache. * - * <p>The <code>//tools/defaults</code> package provides a mechanism let tool locations be - * specified over the commandline, without requiring any special support in the rule code. - * As such, it can be used in genrule <code>$(location)</code> substitutions. + * <p>The <code>//tools/defaults</code> package provides a mechanism let tool locations be specified + * over the commandline, without requiring any special support in the rule code. As such, it can be + * used in genrule <code>$(location)</code> substitutions. * * <p>It works as follows: - * <ul> - * - * <li> SomeLanguage.createCompileAction will refer to a host-configured target for the - * compiler by looking for - * <code>env.getHostPrerequisiteArtifact("$somelanguage_compiler")</code>. - * - * <li> the attribute <code>$somelanguage_compiler</code> is defined in the - * {@link RuleDefinition} subclass for that language. - * - * <li> if the attribute cannot be set on the command-line, its value may be a normal label. - * - * <li> if the attribute can be set on the command-line, its value will be - * <code>//tools/defaults:somelanguage_compiler</code>. - * - * <li> in the latter case, the {@link BuildConfiguration.Fragment} subclass will define the - * option (with an existing target, eg. <code>//third_party/somelanguage:compiler</code>), and - * return the name in its implementation of {@link FragmentOptions#getDefaultsLabels}. - * - * <li> On startup, the rule is wired up with <code>//tools/defaults:somelanguage_compiler</code>. - * - * <li> On starting a build, the <code>//tools/defaults</code> package is synthesized, using - * the values as specified on the command-line. The contents of - * <code>tools/defaults/BUILD</code> is ignored. - * - * <li> Hence, changes in the command line values for tools are now handled exactly as if they - * were changes in a BUILD file. - * - * <li> The file <code>tools/defaults/BUILD</code> must exist, so we create a package in that - * location. - * - * <li> The code in {@link DefaultsPackage} can dump the synthesized package as a BUILD file, - * so external tooling does not need to understand the intricacies of handling command-line - * options. * + * <ul> + * <li>SomeLanguage.createCompileAction will refer to a host-configured target for the compiler by + * looking for <code>env.getHostPrerequisiteArtifact("$somelanguage_compiler")</code>. + * <li>the attribute <code>$somelanguage_compiler</code> is defined in the {@link RuleDefinition} + * subclass for that language. + * <li>if the attribute cannot be set on the command-line, its value may be a normal label. + * <li>if the attribute can be set on the command-line, its value will be <code> + * //tools/defaults:somelanguage_compiler</code>. + * <li>in the latter case, the {@link BuildConfiguration.Fragment} subclass will define the option + * (with an existing target, eg. <code>//third_party/somelanguage:compiler</code>), and return + * the name in its implementation of {@link FragmentOptions#getDefaultsLabels}. + * <li>On startup, the rule is wired up with <code>//tools/defaults:somelanguage_compiler</code>. + * <li>On starting a build, the <code>//tools/defaults</code> package is synthesized, using the + * values as specified on the command-line. The contents of <code>tools/defaults/BUILD</code> + * is ignored. + * <li>Hence, changes in the command line values for tools are now handled exactly as if they were + * changes in a BUILD file. + * <li>The file <code>tools/defaults/BUILD</code> must exist, so we create a package in that + * location. + * <li>The code in {@link DefaultsPackage} can dump the synthesized package as a BUILD file, so + * external tooling does not need to understand the intricacies of handling command-line + * options. * </ul> * - * <p>For built-in rules (as opposed to genrules), late-bound labels provide an alternative - * method of depending on command-line values. These work by declaring attribute default values - * to be {@link LateBoundLabel} instances, whose <code>resolve(Rule rule, AttributeMap attributes, - * T configuration)</code> method will have access to {@link BuildConfiguration}, which in turn - * may depend on command line flag values. + * <p>For built-in rules (as opposed to genrules), late-bound labels provide an alternative method + * of depending on command-line values. These work by declaring attribute default values to be + * {@link LateBoundDefault} instances, whose <code>resolve(Rule rule, AttributeMap attributes, + * FragmentT configuration)</code> method will have access to a {@link BuildConfiguration.Fragment}, + * which in turn may depend on command line flag values. */ public final class DefaultsPackage { diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java index 21a5a31ffd..39f1dcbf93 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java @@ -74,7 +74,7 @@ import com.google.devtools.build.lib.bazel.rules.workspace.MavenServerRule; import com.google.devtools.build.lib.bazel.rules.workspace.NewGitRepositoryRule; import com.google.devtools.build.lib.bazel.rules.workspace.NewHttpArchiveRule; import com.google.devtools.build.lib.cmdline.Label; -import com.google.devtools.build.lib.packages.Attribute.LateBoundLabel; +import com.google.devtools.build.lib.packages.Attribute.LateBoundDefault; import com.google.devtools.build.lib.rules.Alias.AliasRule; import com.google.devtools.build.lib.rules.android.AarImportBaseRule; import com.google.devtools.build.lib.rules.android.AndroidBinaryOnlyRule; @@ -464,8 +464,7 @@ public class BazelRuleClassProvider { new RuleSet() { @Override public void init(Builder builder) { - LateBoundLabel<BuildConfiguration> hostJdkAttribute = - JavaSemantics.hostJdkAttribute(builder); + LateBoundDefault<?, Label> hostJdkAttribute = JavaSemantics.hostJdkAttribute(builder); BazelJavaProtoAspect bazelJavaProtoAspect = new BazelJavaProtoAspect(hostJdkAttribute); BazelJavaLiteProtoAspect bazelJavaLiteProtoAspect = new BazelJavaLiteProtoAspect(hostJdkAttribute); diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/android/BazelAndroidRuleClasses.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/BazelAndroidRuleClasses.java index ca5a6699dd..abc40e90ef 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/rules/android/BazelAndroidRuleClasses.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/BazelAndroidRuleClasses.java @@ -16,13 +16,13 @@ package com.google.devtools.build.lib.bazel.rules.android; 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.rules.android.AndroidRuleClasses.getAndroidSdkLabel; 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.packages.RuleClass; import com.google.devtools.build.lib.rules.android.AndroidRuleClasses; -import com.google.devtools.build.lib.rules.android.AndroidRuleClasses.AndroidSdkLabel; import com.google.devtools.build.lib.rules.android.AndroidToolsDefaultsJar; /** Rule class definitions for Android rules. */ @@ -37,8 +37,9 @@ public class BazelAndroidRuleClasses { .add( attr(":android_sdk", LABEL) .allowedRuleClasses("android_sdk", "filegroup") - .value(new AndroidSdkLabel( - environment.getToolsLabel(AndroidRuleClasses.DEFAULT_SDK)))) + .value( + getAndroidSdkLabel( + environment.getToolsLabel(AndroidRuleClasses.DEFAULT_SDK)))) .build(); } diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/cpp/BazelCppRuleClasses.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/cpp/BazelCppRuleClasses.java index dc79061223..b5778480ab 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/rules/cpp/BazelCppRuleClasses.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/cpp/BazelCppRuleClasses.java @@ -42,15 +42,12 @@ import com.google.devtools.build.lib.analysis.BaseRuleClasses; import com.google.devtools.build.lib.analysis.PlatformConfiguration; import com.google.devtools.build.lib.analysis.RuleDefinition; import com.google.devtools.build.lib.analysis.RuleDefinitionEnvironment; -import com.google.devtools.build.lib.analysis.config.BuildConfiguration; import com.google.devtools.build.lib.cmdline.Label; import com.google.devtools.build.lib.packages.Attribute; -import com.google.devtools.build.lib.packages.Attribute.LateBoundLabel; +import com.google.devtools.build.lib.packages.Attribute.LateBoundDefault; import com.google.devtools.build.lib.packages.AttributeMap; import com.google.devtools.build.lib.packages.BuildType; import com.google.devtools.build.lib.packages.ImplicitOutputsFunction.SafeImplicitOutputsFunction; -import com.google.devtools.build.lib.packages.RawAttributeMapper; -import com.google.devtools.build.lib.packages.Rule; import com.google.devtools.build.lib.packages.RuleClass; import com.google.devtools.build.lib.packages.RuleClass.Builder; import com.google.devtools.build.lib.packages.RuleClass.Builder.RuleClassType; @@ -73,36 +70,30 @@ public class BazelCppRuleClasses { static final SafeImplicitOutputsFunction CC_BINARY_IMPLICIT_OUTPUTS = fromFunctions(CppRuleClasses.CC_BINARY_STRIPPED, CppRuleClasses.CC_BINARY_DEBUG_PACKAGE); - public static final LateBoundLabel<BuildConfiguration> STL = - new LateBoundLabel<BuildConfiguration>() { - @Override - public Label resolve(Rule rule, AttributeMap attributes, - BuildConfiguration configuration) { - return getStl(rule, configuration); - } - }; - /** * Returns the STL prerequisite of the rule. * - * <p>If rule has an implicit $stl_default attribute returns STL version set on the - * command line or if not set, the value of the $stl_default attribute. Returns - * {@code null} otherwise. + * <p>If rule has an implicit $stl_default attribute returns STL version set on the command line + * or if not set, the value of the $stl_default attribute. Returns {@code null} otherwise. */ - private static Label getStl(Rule rule, BuildConfiguration original) { - Label stl = null; - if (rule.getRuleClassObject().hasAttr("$stl_default", BuildType.LABEL)) { - Label stlConfigLabel = original.getFragment(CppConfiguration.class).getStl(); - Label stlRuleLabel = RawAttributeMapper.of(rule).get("$stl_default", BuildType.LABEL); - if (stlConfigLabel == null) { - stl = stlRuleLabel; - } else if (!stlConfigLabel.equals(rule.getLabel()) && stlRuleLabel != null) { - // prevents self-reference and a cycle through standard STL in the dependency graph - stl = stlConfigLabel; - } - } - return stl; - } + public static final LateBoundDefault<?, Label> STL = + LateBoundDefault.fromTargetConfiguration( + CppConfiguration.class, + null, + (rule, attributes, cppConfig) -> { + Label stl = null; + if (attributes.has("$stl_default", BuildType.LABEL)) { + Label stlConfigLabel = cppConfig.getStl(); + Label stlRuleLabel = attributes.get("$stl_default", BuildType.LABEL); + if (stlConfigLabel == null) { + stl = stlRuleLabel; + } else if (!stlConfigLabel.equals(rule.getLabel()) && stlRuleLabel != null) { + // prevents self-reference and a cycle through standard STL in the dependency graph + stl = stlConfigLabel; + } + } + return stl; + }); static final FileTypeSet ALLOWED_SRC_FILES = FileTypeSet.of( @@ -421,14 +412,14 @@ public class BazelCppRuleClasses { } /** Implementation for the :lipo_context attribute. */ - static final LateBoundLabel<BuildConfiguration> LIPO_CONTEXT = - new LateBoundLabel<BuildConfiguration>() { - @Override - public Label resolve(Rule rule, AttributeMap attributes, BuildConfiguration configuration) { - Label result = configuration.getFragment(CppConfiguration.class).getLipoContextLabel(); - return (rule == null || rule.getLabel().equals(result)) ? null : result; - } - }; + static final LateBoundDefault<?, Label> LIPO_CONTEXT = + LateBoundDefault.fromTargetConfiguration( + CppConfiguration.class, + null, + (rule, attributes, cppConfig) -> { + Label result = cppConfig.getLipoContextLabel(); + return (rule == null || rule.getLabel().equals(result)) ? null : result; + }); /** * Helper rule class. diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/java/proto/BazelJavaLiteProtoAspect.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/java/proto/BazelJavaLiteProtoAspect.java index 041956afe6..43139b40c5 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/rules/java/proto/BazelJavaLiteProtoAspect.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/java/proto/BazelJavaLiteProtoAspect.java @@ -14,9 +14,9 @@ package com.google.devtools.build.lib.bazel.rules.java.proto; -import com.google.devtools.build.lib.analysis.config.BuildConfiguration; import com.google.devtools.build.lib.bazel.rules.java.BazelJavaSemantics; -import com.google.devtools.build.lib.packages.Attribute.LateBoundLabel; +import com.google.devtools.build.lib.cmdline.Label; +import com.google.devtools.build.lib.packages.Attribute.LateBoundDefault; import com.google.devtools.build.lib.rules.java.proto.JavaLiteProtoAspect; /** An Aspect which BazelJavaLiteProtoLibrary injects to build Java Lite protos. */ @@ -25,7 +25,7 @@ public class BazelJavaLiteProtoAspect extends JavaLiteProtoAspect { public static final String DEFAULT_PROTO_TOOLCHAIN_LABEL = "@com_google_protobuf_javalite//:javalite_toolchain"; - public BazelJavaLiteProtoAspect(LateBoundLabel<BuildConfiguration> hostJdkAttribute) { + public BazelJavaLiteProtoAspect(LateBoundDefault<?, Label> hostJdkAttribute) { super( BazelJavaSemantics.INSTANCE, null /* jacocoLabel */, diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/java/proto/BazelJavaProtoAspect.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/java/proto/BazelJavaProtoAspect.java index 9aed78a240..98f37d0fa8 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/rules/java/proto/BazelJavaProtoAspect.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/java/proto/BazelJavaProtoAspect.java @@ -20,13 +20,13 @@ import com.google.common.collect.ImmutableList; import com.google.devtools.build.lib.actions.Artifact; import com.google.devtools.build.lib.analysis.RuleContext; import com.google.devtools.build.lib.analysis.TransitiveInfoCollection; -import com.google.devtools.build.lib.analysis.config.BuildConfiguration; import com.google.devtools.build.lib.bazel.rules.java.BazelJavaSemantics; +import com.google.devtools.build.lib.cmdline.Label; import com.google.devtools.build.lib.collect.nestedset.NestedSet; import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; import com.google.devtools.build.lib.packages.AspectDefinition; import com.google.devtools.build.lib.packages.AspectParameters; -import com.google.devtools.build.lib.packages.Attribute.LateBoundLabel; +import com.google.devtools.build.lib.packages.Attribute.LateBoundDefault; import com.google.devtools.build.lib.rules.java.proto.JavaProtoAspect; import com.google.devtools.build.lib.rules.java.proto.RpcSupport; import com.google.devtools.build.lib.rules.proto.ProtoCompileActionBuilder; @@ -35,7 +35,7 @@ import java.util.List; /** An Aspect which BazelJavaProtoLibrary injects to build Java SPEED protos. */ public class BazelJavaProtoAspect extends JavaProtoAspect { - public BazelJavaProtoAspect(LateBoundLabel<BuildConfiguration> hostJdkAttribute) { + public BazelJavaProtoAspect(LateBoundDefault<?, Label> hostJdkAttribute) { super( BazelJavaSemantics.INSTANCE, null, /* jacocoAttr */ diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/python/BazelPyRuleClasses.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/python/BazelPyRuleClasses.java index 006b82c660..dee60f9ba7 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/rules/python/BazelPyRuleClasses.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/python/BazelPyRuleClasses.java @@ -26,12 +26,9 @@ 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.BuildConfiguration; import com.google.devtools.build.lib.bazel.rules.cpp.BazelCppRuleClasses; import com.google.devtools.build.lib.cmdline.Label; -import com.google.devtools.build.lib.packages.Attribute.LateBoundLabel; -import com.google.devtools.build.lib.packages.AttributeMap; -import com.google.devtools.build.lib.packages.Rule; +import com.google.devtools.build.lib.packages.Attribute.LateBoundDefault; import com.google.devtools.build.lib.packages.RuleClass; import com.google.devtools.build.lib.packages.RuleClass.Builder.RuleClassType; import com.google.devtools.build.lib.packages.TriState; @@ -46,13 +43,11 @@ import com.google.devtools.build.lib.util.FileType; public final class BazelPyRuleClasses { public static final FileType PYTHON_SOURCE = FileType.of(".py"); - public static final LateBoundLabel<BuildConfiguration> PY_INTERPRETER = - new LateBoundLabel<BuildConfiguration>() { - @Override - public Label resolve(Rule rule, AttributeMap attributes, BuildConfiguration configuration) { - return configuration.getFragment(BazelPythonConfiguration.class).getPythonTop(); - } - }; + public static final LateBoundDefault<?, Label> PY_INTERPRETER = + LateBoundDefault.fromTargetConfiguration( + BazelPythonConfiguration.class, + null, + (rule, attributes, bazelPythonConfig) -> bazelPythonConfig.getPythonTop()); /** * Base class for Python rule definitions. 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 5a020be02f..2fedb6a0b5 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 @@ -28,7 +28,6 @@ import com.google.common.collect.Iterables; import com.google.common.collect.Ordering; import com.google.common.collect.Sets; import com.google.devtools.build.lib.analysis.TransitiveInfoProvider; -import com.google.devtools.build.lib.cmdline.Label; import com.google.devtools.build.lib.concurrent.ThreadSafety; import com.google.devtools.build.lib.events.EventHandler; import com.google.devtools.build.lib.events.Location; @@ -676,9 +675,9 @@ public final class Attribute implements Comparable<Attribute> { /** * Sets the attribute default value to be late-bound, i.e., it is derived from the build - * configuration. + * configuration and/or the rule's configured attributes. */ - public Builder<TYPE> value(LateBoundDefault<?> defaultValue) { + public Builder<TYPE> value(LateBoundDefault<?, ? extends TYPE> defaultValue) { Preconditions.checkState(!valueSet, "the default value is already set"); Preconditions.checkState(name.isEmpty() || isLateBound(name)); value = defaultValue; @@ -1549,137 +1548,204 @@ public final class Attribute implements Comparable<Attribute> { } } + // TODO(b/65746853): Remove documentation about accepting BuildConfiguration when uses are cleaned + // up. /** - * Marker interface for late-bound values. Unfortunately, we can't refer to BuildConfiguration - * right now, since that is in a separate compilation unit. - * - * <p>Implementations of this interface must be immutable. + * Provider of values for late-bound attributes. See + * {@link Attribute#value(LateBoundDefault<?, ? extends TYPE> value)}. * * <p>Use sparingly - having different values for attributes during loading and analysis can * confuse users. + * + * @param <FragmentT> The type of value that is used to compute this value. This is usually a + * subclass of BuildConfiguration.Fragment. It may also be Void to receive null, or + * BuildConfiguration itself to receive the entire configuration. + * @param <ValueT> The type of value returned by this class. */ - public interface LateBoundDefault<T> { + @Immutable + public static final class LateBoundDefault<FragmentT, ValueT> { /** - * Whether to look up the label in the host configuration. This is only here for host - * compilation tools - we usually need to look up labels in the target configuration. + * Functional interface for computing the value of a late-bound attribute. * - * <p>This method only sets the configuration passed to {@link #resolve}. If you want the - * dependency to also be analyzed in the host configuration, use - * {@link ConfigurationTransition#HOST}. + * <p>Implementations of this interface must be immutable. */ - boolean useHostConfiguration(); + @FunctionalInterface + public interface Resolver<FragmentT, ValueT> { + ValueT resolve(Rule rule, AttributeMap attributeMap, FragmentT input); + } - /** - * Returns the set of required configuration fragments, i.e., fragments that will be accessed by - * the code. - */ - Set<Class<?>> getRequiredConfigurationFragments(); + private final boolean useHostConfiguration; + private final ValueT defaultValue; + private final Class<FragmentT> fragmentClass; + private final Resolver<FragmentT, ValueT> resolver; /** - * The default value for the attribute that is set during the loading phase. + * Creates a new LateBoundDefault which uses the rule, its configured attributes, and a fragment + * of the target configuration. + * + * <p>Note that the configuration fragment here does not take into account any transitions that + * are on the attribute with this LateBoundDefault as its value. The configuration will be the + * same as the configuration given to the target bearing the attribute. + * + * <p>Nearly all LateBoundDefaults should use this constructor. There are few situations where + * it isn't the appropriate option. + * + * <p>If you want a late-bound dependency which is configured in the host configuration, just + * use this method with {@link ConfigurationTransition#HOST}. If you also need to decide the + * label of the dependency with information gained from the host configuration - and it's very + * unlikely that you do - you can use {@link #fromHostConfiguration} as well. + * + * <p>If you want to decide an attribute's value based on the value of its other attributes, + * use a subclass of {@link ComputedDefault}. The only time you should need + * {@link #fromRuleAndAttributes} is if you need access to three or more configurable + * attributes, or if you need to match names with a late-bound attribute on another rule. + * + * <p>If you have a constant-valued attribute, but you need it to have the same name as an + * attribute on another rule which is late-bound, use {@link #fromConstant} or + * {@link #alwaysNull}. + * + * @param fragmentClass The fragment to receive from the target configuration. May also be + * BuildConfiguration.class to receive the entire configuration (deprecated) - in this case, + * you must only use methods of BuildConfiguration itself, and not use any fragments. + * @param defaultValue The default value to return at loading time, when the configuration is + * not available. + * @param resolver A function which will compute the actual value with the configuration. */ - Object getDefault(); + public static <FragmentT, ValueT> LateBoundDefault<FragmentT, ValueT> fromTargetConfiguration( + Class<FragmentT> fragmentClass, ValueT defaultValue, Resolver<FragmentT, ValueT> resolver) { + Preconditions.checkArgument( + !fragmentClass.equals(Void.class), + "Use fromRuleAndAttributesOnly to specify a LateBoundDefault which does not use " + + "configuration."); + return new LateBoundDefault<>(false, fragmentClass, defaultValue, resolver); + } /** - * The actual value for the attribute for the analysis phase, which depends on the build - * configuration. Note that configurations transitions are applied after the late-bound - * attribute was evaluated. + * Creates a new LateBoundDefault which uses the rule, its configured attributes, and a fragment + * of the host configuration. * - * @param rule the rule being evaluated - * @param attributes interface for retrieving the values of the rule's other attributes - * @param o the configuration to evaluate with + * <p>This should only be necessary in very specialized cases. In almost all cases, you don't + * need this method, just {@link #fromTargetConfiguration} and + * {@link ConfigurationTransition#HOST}. + * + * <p>This method only affects the configuration fragment passed to {@link #resolve}. You must + * also use {@link ConfigurationTransition#HOST}, so that the dependency will be analyzed in the + * host configuration. + * + * @param fragmentClass The fragment to receive from the host configuration. May also be + * BuildConfiguration.class to receive the entire configuration (deprecated) - in this case, + * you must only use methods of BuildConfiguration itself, and not use any fragments. + * It is very rare that a LateBoundDefault should need a host configuration fragment; use + * {@link #fromTargetConfiguration} in most cases. + * @param defaultValue The default value to return at loading time, when the configuration is + * not available. + * @param resolver A function which will compute the actual value with the configuration. + */ + public static <FragmentT, ValueT> LateBoundDefault<FragmentT, ValueT> fromHostConfiguration( + Class<FragmentT> fragmentClass, ValueT defaultValue, Resolver<FragmentT, ValueT> resolver) { + Preconditions.checkArgument( + !fragmentClass.equals(Void.class), + "Use fromRuleAndAttributesOnly to specify a LateBoundDefault which does not use " + + "configuration."); + return new LateBoundDefault<>(true, fragmentClass, defaultValue, resolver); + } + + /** + * Creates a new LateBoundDefault which uses only the rule and its configured attributes. + * + * <p>This should only be necessary in very specialized cases. In almost all cases, you don't + * need this method, just use {@link ComputedDefault}. + * + * <p>This is used primarily for computing values based on three or more configurable + * attributes and/or matching names with late-bound attributes on other rules. + * + * @param defaultValue The default value to return when the configuration is not available at + * loading time. + * @param resolver A function which will compute the actual value with the configuration. */ - Object resolve(Rule rule, AttributeMap attributes, T o) - throws EvalException, InterruptedException; - } - - /** - * Abstract super class for label-typed {@link LateBoundDefault} implementations that simplifies - * the client code a little and makes it a bit more type-safe. - */ - public abstract static class LateBoundLabel<T> implements LateBoundDefault<T> { - private final Label label; - private final ImmutableSet<Class<?>> requiredConfigurationFragments; - - public LateBoundLabel() { - this((Label) null); - } - - public LateBoundLabel(Class<?>... requiredConfigurationFragments) { - this((Label) null, requiredConfigurationFragments); + public static <ValueT> LateBoundDefault<Void, ValueT> fromRuleAndAttributesOnly( + ValueT defaultValue, Resolver<Void, ValueT> resolver) { + return new LateBoundDefault<>(false, Void.class, defaultValue, resolver); } - public LateBoundLabel(Label label) { - this.label = label; - this.requiredConfigurationFragments = ImmutableSet.of(); + /** + * Creates a new LateBoundDefault which always returns the given value. + * + * <p>This is used primarily for matching names with late-bound attributes on other rules and + * for testing. Use normal default values if the name does not matter. + */ + public static <ValueT> LateBoundDefault<Void, ValueT> fromConstant(final ValueT defaultValue) { + if (defaultValue == null) { + return alwaysNull(); + } + return new LateBoundDefault<>( + false, Void.class, defaultValue, (rule, attributes, unused) -> defaultValue); } - public LateBoundLabel(Label label, Class<?>... requiredConfigurationFragments) { - this.label = label; - this.requiredConfigurationFragments = ImmutableSet.copyOf(requiredConfigurationFragments); + /** + * Creates a new LateBoundDefault which always returns null. + * + * <p>This is used primarily for matching names with late-bound attributes on other rules and + * for testing. Use normal default values if the name does not matter. + */ + @SuppressWarnings("unchecked") // bivariant implementation + public static <ValueT> LateBoundDefault<Void, ValueT> alwaysNull() { + return (LateBoundDefault<Void, ValueT>) ALWAYS_NULL; } - public LateBoundLabel(String label) { - this(Label.parseAbsoluteUnchecked(label)); - } + private static final LateBoundDefault<Void, Void> ALWAYS_NULL = + new LateBoundDefault<>(false, Void.class, null, (rule, attributes, unused) -> null); - public LateBoundLabel(String label, Class<?>... requiredConfigurationFragments) { - this(Label.parseAbsoluteUnchecked(label), requiredConfigurationFragments); + private LateBoundDefault( + boolean useHostConfiguration, + Class<FragmentT> fragmentClass, + ValueT defaultValue, + Resolver<FragmentT, ValueT> resolver) { + this.useHostConfiguration = useHostConfiguration; + this.defaultValue = defaultValue; + this.fragmentClass = fragmentClass; + this.resolver = resolver; } - @Override + /** + * Whether to look up the label in the host configuration. This is only here for host + * compilation tools - we usually need to look up labels in the target configuration. + */ public boolean useHostConfiguration() { - return false; + return useHostConfiguration; } - @Override - public ImmutableSet<Class<?>> getRequiredConfigurationFragments() { - return requiredConfigurationFragments; - } - - @Override - public final Label getDefault() { - return label; - } - - @Override - public abstract Label resolve(Rule rule, AttributeMap attributes, T configuration); - } - - /** - * Abstract super class for label-list-typed {@link LateBoundDefault} implementations that - * simplifies the client code a little and makes it a bit more type-safe. - */ - public abstract static class LateBoundLabelList<T> implements LateBoundDefault<T> { - private final ImmutableList<Label> labels; - private final ImmutableSet<Class<?>> requiredConfigurationFragments; - - public LateBoundLabelList(Class<?>... requiredConfigurationFragments) { - this(ImmutableList.<Label>of(), requiredConfigurationFragments); - } - - public LateBoundLabelList(List<Label> labels, Class<?>... requiredConfigurationFragments) { - this.labels = ImmutableList.copyOf(labels); - this.requiredConfigurationFragments = ImmutableSet.copyOf(requiredConfigurationFragments); - } - - @Override - public boolean useHostConfiguration() { - return false; + /** + * Returns the input type that the attribute expects. This is almost always a configuration + * fragment to be retrieved from the target's configuration (or the host configuration). + * + * <p>It may also be {@link Void} to receive null. This is rarely necessary, but can be used, + * e.g., if the attribute is named to match an attribute in another rule which is late-bound. + * + * <p>It may also be BuildConfiguration to receive the entire configuration. This is deprecated, + * and only necessary when the default is computed from methods of BuildConfiguration itself. + */ + public Class<FragmentT> getFragmentClass() { + return fragmentClass; } - @Override - public ImmutableSet<Class<?>> getRequiredConfigurationFragments() { - return requiredConfigurationFragments; + /** The default value for the attribute that is set during the loading phase. */ + public ValueT getDefault() { + return defaultValue; } - @Override - public final List<Label> getDefault() { - return labels; + /** + * The actual value for the attribute for the analysis phase, which depends on the build + * configuration. Note that configurations transitions are applied after the late-bound + * attribute was evaluated. + * + * @param rule the rule being evaluated + * @param attributes interface for retrieving the values of the rule's other attributes + * @param input the configuration fragment to evaluate with + */ + public ValueT resolve(Rule rule, AttributeMap attributes, FragmentT input) { + return resolver.resolve(rule, attributes, input); } - - @Override - public abstract List<Label> resolve(Rule rule, AttributeMap attributes, T configuration); } private final String name; @@ -1776,7 +1842,7 @@ public final class Attribute implements Comparable<Attribute> { "late bound attributes require a default value that is late bound (and vice versa): %s", name); if (isLateBound(name)) { - LateBoundDefault<?> lateBoundDefault = (LateBoundDefault<?>) defaultValue; + LateBoundDefault<?, ?> lateBoundDefault = (LateBoundDefault<?, ?>) defaultValue; Preconditions.checkArgument(!lateBoundDefault.useHostConfiguration() || (configTransition == ConfigurationTransition.HOST), "a late bound default value using the host configuration must use the host transition"); @@ -2045,8 +2111,8 @@ public final class Attribute implements Comparable<Attribute> { public Object getDefaultValue(Rule rule) { if (!getCondition().apply(rule == null ? null : NonconfigurableAttributeMapper.of(rule))) { return null; - } else if (defaultValue instanceof LateBoundDefault<?>) { - return ((LateBoundDefault<?>) defaultValue).getDefault(); + } else if (defaultValue instanceof LateBoundDefault<?, ?>) { + return ((LateBoundDefault<?, ?>) defaultValue).getDefault(); } else { return defaultValue; } @@ -2061,9 +2127,9 @@ public final class Attribute implements Comparable<Attribute> { return defaultValue; } - public LateBoundDefault<?> getLateBoundDefault() { + public LateBoundDefault<?, ?> getLateBoundDefault() { Preconditions.checkState(isLateBound()); - return (LateBoundDefault<?>) defaultValue; + return (LateBoundDefault<?, ?>) defaultValue; } /** diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidRuleClasses.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidRuleClasses.java index 2842572fd5..b2f064848e 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidRuleClasses.java +++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidRuleClasses.java @@ -39,7 +39,7 @@ import com.google.devtools.build.lib.analysis.config.BuildOptions; import com.google.devtools.build.lib.cmdline.Label; import com.google.devtools.build.lib.packages.Attribute; import com.google.devtools.build.lib.packages.Attribute.AllowedValueSet; -import com.google.devtools.build.lib.packages.Attribute.LateBoundLabel; +import com.google.devtools.build.lib.packages.Attribute.LateBoundDefault; import com.google.devtools.build.lib.packages.Attribute.SplitTransition; import com.google.devtools.build.lib.packages.AttributeMap; import com.google.devtools.build.lib.packages.BuildType; @@ -191,17 +191,12 @@ public final class AndroidRuleClasses { fromTemplates("%{name}_images/emulator-meta-data.pb"); static final FileType APK = FileType.of(".apk"); - /** - * The default label of android_sdk option - */ - public static final class AndroidSdkLabel extends LateBoundLabel<BuildConfiguration> { - public AndroidSdkLabel(Label androidSdk) { - super(androidSdk, AndroidConfiguration.class); - } - @Override - public Label resolve(Rule rule, AttributeMap attributes, BuildConfiguration configuration) { - return configuration.getFragment(AndroidConfiguration.class).getSdk(); - } + /** The default label of android_sdk option */ + public static LateBoundDefault<?, Label> getAndroidSdkLabel(Label androidSdk) { + return LateBoundDefault.fromTargetConfiguration( + AndroidConfiguration.class, + androidSdk, + (rule, attributes, configuration) -> configuration.getSdk()); } public static final SplitTransition<BuildOptions> ANDROID_SPLIT_TRANSITION = @@ -555,7 +550,7 @@ public final class AndroidRuleClasses { .add( attr(":android_sdk", LABEL) .allowedRuleClasses("android_sdk", "filegroup") - .value(new AndroidSdkLabel(env.getToolsLabel(AndroidRuleClasses.DEFAULT_SDK)))) + .value(getAndroidSdkLabel(env.getToolsLabel(AndroidRuleClasses.DEFAULT_SDK)))) /* <!-- #BLAZE_RULE($android_base).ATTRIBUTE(plugins) --> Java compiler plugins to run at compile-time. Every <code>java_plugin</code> specified in diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/DexArchiveAspect.java b/src/main/java/com/google/devtools/build/lib/rules/android/DexArchiveAspect.java index b3a5ff58e7..8f4a8ff45c 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/android/DexArchiveAspect.java +++ b/src/main/java/com/google/devtools/build/lib/rules/android/DexArchiveAspect.java @@ -146,7 +146,7 @@ public final class DexArchiveAspect extends NativeAspectClass implements Configu attr(":dex_archive_android_sdk", LABEL) .allowedRuleClasses("android_sdk", "filegroup") .value( - new AndroidRuleClasses.AndroidSdkLabel( + AndroidRuleClasses.getAndroidSdkLabel( Label.parseAbsoluteUnchecked( toolsRepository + AndroidRuleClasses.DEFAULT_SDK)))) .requiresConfigurationFragments(AndroidConfiguration.class) diff --git a/src/main/java/com/google/devtools/build/lib/rules/apple/AppleToolchain.java b/src/main/java/com/google/devtools/build/lib/rules/apple/AppleToolchain.java index a380f52713..0cc09b83ea 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/apple/AppleToolchain.java +++ b/src/main/java/com/google/devtools/build/lib/rules/apple/AppleToolchain.java @@ -22,12 +22,9 @@ import com.google.common.collect.ImmutableMap; import com.google.devtools.build.lib.analysis.RuleContext; import com.google.devtools.build.lib.analysis.RuleDefinition; import com.google.devtools.build.lib.analysis.RuleDefinitionEnvironment; -import com.google.devtools.build.lib.analysis.config.BuildConfiguration; 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.LateBoundLabel; -import com.google.devtools.build.lib.packages.AttributeMap; -import com.google.devtools.build.lib.packages.Rule; +import com.google.devtools.build.lib.packages.Attribute.LateBoundDefault; import com.google.devtools.build.lib.packages.RuleClass; import com.google.devtools.build.lib.packages.RuleClass.Builder; import com.google.devtools.build.lib.packages.RuleClass.Builder.RuleClassType; @@ -151,20 +148,13 @@ public class AppleToolchain { return sdkDir() + relativePath; } - /** - * The default label of the build-wide {@code xcode_config} configuration rule. - */ - @Immutable - public static final class XcodeConfigLabel extends LateBoundLabel<BuildConfiguration> { - public XcodeConfigLabel(String toolsRepository) { - super(toolsRepository + AppleCommandLineOptions.DEFAULT_XCODE_VERSION_CONFIG_LABEL, - AppleConfiguration.class); - } - - @Override - public Label resolve(Rule rule, AttributeMap attributes, BuildConfiguration configuration) { - return configuration.getFragment(AppleConfiguration.class).getXcodeConfigLabel(); - } + /** The default label of the build-wide {@code xcode_config} configuration rule. */ + public static LateBoundDefault<?, Label> getXcodeConfigLabel(String toolsRepository) { + return LateBoundDefault.fromTargetConfiguration( + AppleConfiguration.class, + Label.parseAbsoluteUnchecked( + toolsRepository + AppleCommandLineOptions.DEFAULT_XCODE_VERSION_CONFIG_LABEL), + (rule, attributes, appleConfig) -> appleConfig.getXcodeConfigLabel()); } /** @@ -180,11 +170,12 @@ public class AppleToolchain { @Override public RuleClass build(Builder builder, RuleDefinitionEnvironment env) { return builder - .add(attr(XcodeConfigRule.XCODE_CONFIG_ATTR_NAME, LABEL) - .allowedRuleClasses("xcode_config") - .checkConstraints() - .direct_compile_time_input() - .value(new XcodeConfigLabel(toolsRepository))) + .add( + attr(XcodeConfigRule.XCODE_CONFIG_ATTR_NAME, LABEL) + .allowedRuleClasses("xcode_config") + .checkConstraints() + .direct_compile_time_input() + .value(getXcodeConfigLabel(toolsRepository))) .build(); } @Override diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchain.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchain.java index 0bd4093864..11781594b5 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchain.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchain.java @@ -70,7 +70,7 @@ public class CcToolchain implements RuleConfiguredTargetFactory { public static final String CC_TOOLCHAIN_DEFAULT_ATTRIBUTE_NAME = ":cc_toolchain"; /** Default attribute name for the c++ toolchain type */ - public static final String CC_TOOLCHAIN_TYPE_ATTRIBUTE_NAME = ":cc_toolchain_type"; + public static final String CC_TOOLCHAIN_TYPE_ATTRIBUTE_NAME = "$cc_toolchain_type"; /** * This file (found under the sysroot) may be unconditionally included in every C/C++ compilation. diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainRule.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainRule.java index 23cc7fc326..6672ca93bd 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainRule.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainRule.java @@ -25,10 +25,8 @@ import com.google.devtools.build.lib.analysis.BaseRuleClasses; import com.google.devtools.build.lib.analysis.MakeVariableInfo; import com.google.devtools.build.lib.analysis.RuleDefinition; import com.google.devtools.build.lib.analysis.RuleDefinitionEnvironment; -import com.google.devtools.build.lib.analysis.config.BuildConfiguration; import com.google.devtools.build.lib.cmdline.Label; -import com.google.devtools.build.lib.packages.Attribute.LateBoundLabel; -import com.google.devtools.build.lib.packages.AttributeMap; +import com.google.devtools.build.lib.packages.Attribute.LateBoundDefault; import com.google.devtools.build.lib.packages.Rule; import com.google.devtools.build.lib.packages.RuleClass; import com.google.devtools.build.lib.packages.RuleClass.Builder; @@ -66,13 +64,11 @@ public final class CcToolchainRule implements RuleDefinition { return ruleClass.endsWith("cc_toolchain"); } - private static final LateBoundLabel<BuildConfiguration> LIBC_TOP = - new LateBoundLabel<BuildConfiguration>(CppConfiguration.class) { - @Override - public Label resolve(Rule rule, AttributeMap attributes, BuildConfiguration configuration) { - return configuration.getFragment(CppConfiguration.class).getSysrootLabel(); - } - }; + private static final LateBoundDefault<?, Label> LIBC_TOP = + LateBoundDefault.fromTargetConfiguration( + CppConfiguration.class, + null, + (rule, attributes, cppConfig) -> cppConfig.getSysrootLabel()); @Override public RuleClass build(Builder builder, RuleDefinitionEnvironment env) { @@ -117,19 +113,11 @@ public final class CcToolchainRule implements RuleDefinition { .cfg(HOST) .singleArtifact() .value( - new LateBoundLabel<BuildConfiguration>() { - @Override - public Label resolve( - Rule rule, AttributeMap attributes, BuildConfiguration configuration) { - CppConfiguration cppConfiguration = - configuration.getFragment(CppConfiguration.class); - if (cppConfiguration.isLLVMOptimizedFdo()) { - return zipper; - } else { - return null; - } - } - })) + LateBoundDefault.fromTargetConfiguration( + CppConfiguration.class, + null, + (rule, attributes, cppConfig) -> + cppConfig.isLLVMOptimizedFdo() ? zipper : null))) .add(attr(":libc_top", LABEL).value(LIBC_TOP)) .add( attr(":lipo_context_collector", LABEL) diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppRuleClasses.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppRuleClasses.java index 953044781b..a4ad59ec05 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppRuleClasses.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppRuleClasses.java @@ -33,16 +33,13 @@ import static com.google.devtools.build.lib.rules.cpp.CppFileTypes.VERSIONED_SHA import com.google.common.collect.ImmutableMap; import com.google.devtools.build.lib.analysis.LanguageDependentFragment.LibraryLanguage; import com.google.devtools.build.lib.analysis.RuleDefinitionEnvironment; -import com.google.devtools.build.lib.analysis.config.BuildConfiguration; import com.google.devtools.build.lib.analysis.config.PatchTransition; import com.google.devtools.build.lib.analysis.test.InstrumentedFilesCollector.InstrumentationSpec; import com.google.devtools.build.lib.cmdline.Label; import com.google.devtools.build.lib.packages.Attribute; -import com.google.devtools.build.lib.packages.Attribute.LateBoundLabel; +import com.google.devtools.build.lib.packages.Attribute.LateBoundDefault; import com.google.devtools.build.lib.packages.Attribute.Transition; -import com.google.devtools.build.lib.packages.AttributeMap; import com.google.devtools.build.lib.packages.ImplicitOutputsFunction.SafeImplicitOutputsFunction; -import com.google.devtools.build.lib.packages.Rule; import com.google.devtools.build.lib.packages.RuleTransitionFactory; import com.google.devtools.build.lib.rules.cpp.transitions.DisableLipoTransition; import com.google.devtools.build.lib.rules.cpp.transitions.EnableLipoTransition; @@ -55,17 +52,16 @@ import com.google.devtools.build.lib.util.OsUtils; public class CppRuleClasses { /** * Implementation for the :lipo_context_collector attribute. + * + * <p>This attribute connects a target to the LIPO context target configured with the lipo input + * collector configuration. */ - public static final LateBoundLabel<BuildConfiguration> LIPO_CONTEXT_COLLECTOR = - new LateBoundLabel<BuildConfiguration>() { - @Override - public Label resolve(Rule rule, AttributeMap attributes, BuildConfiguration configuration) { - // This attribute connects a target to the LIPO context target configured with the - // lipo input collector configuration. - CppConfiguration cppConfiguration = configuration.getFragment(CppConfiguration.class); - return cppConfiguration.isLipoOptimization() ? cppConfiguration.getLipoContextLabel() : null; - } - }; + public static final LateBoundDefault<?, Label> LIPO_CONTEXT_COLLECTOR = + LateBoundDefault.fromTargetConfiguration( + CppConfiguration.class, + null, + (rule, attributes, cppConfig) -> + cppConfig.isLipoOptimization() ? cppConfig.getLipoContextLabel() : null); /** * Declares the implementations for C++ transition enums. @@ -91,34 +87,20 @@ public class CppRuleClasses { */ public static final String CROSSTOOL_LABEL = "//tools/cpp:toolchain"; - public static final LateBoundLabel<BuildConfiguration> DEFAULT_MALLOC = - new LateBoundLabel<BuildConfiguration>() { - @Override - public Label resolve(Rule rule, AttributeMap attributes, BuildConfiguration configuration) { - return configuration.getFragment(CppConfiguration.class).customMalloc(); - } - }; + public static final LateBoundDefault<?, Label> DEFAULT_MALLOC = + LateBoundDefault.fromTargetConfiguration( + CppConfiguration.class, null, (rule, attributes, cppConfig) -> cppConfig.customMalloc()); - public static LateBoundLabel<BuildConfiguration> ccToolchainAttribute( + public static LateBoundDefault<CppConfiguration, Label> ccToolchainAttribute( RuleDefinitionEnvironment env) { - return new LateBoundLabel<BuildConfiguration>( - env.getToolsLabel(CROSSTOOL_LABEL), CppConfiguration.class) { - @Override - public Label resolve(Rule rule, AttributeMap attributes, BuildConfiguration configuration) { - return configuration.getFragment(CppConfiguration.class).getCcToolchainRuleLabel(); - } - }; + return LateBoundDefault.fromTargetConfiguration( + CppConfiguration.class, + env.getToolsLabel(CROSSTOOL_LABEL), + (rules, attributes, cppConfig) -> cppConfig.getCcToolchainRuleLabel()); } - public static LateBoundLabel<BuildConfiguration> ccToolchainTypeAttribute( - RuleDefinitionEnvironment env) { - return new LateBoundLabel<BuildConfiguration>( - env.getToolsLabel(CppHelper.TOOLCHAIN_TYPE_LABEL), CppConfiguration.class) { - @Override - public Label resolve(Rule rule, AttributeMap attributes, BuildConfiguration configuration) { - return CppHelper.getCcToolchainType(env.getToolsRepository()); - } - }; + public static Label ccToolchainTypeAttribute(RuleDefinitionEnvironment env) { + return env.getToolsLabel(CppHelper.TOOLCHAIN_TYPE_LABEL); } // Artifacts of these types are discarded from the 'hdrs' attribute in cc rules 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 dd73adffd1..35538cc8c0 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 @@ -31,16 +31,13 @@ import com.google.devtools.build.lib.analysis.RuleContext; import com.google.devtools.build.lib.analysis.TransitiveInfoCollection; import com.google.devtools.build.lib.analysis.TransitiveInfoProvider; import com.google.devtools.build.lib.analysis.TransitiveInfoProviderMap; -import com.google.devtools.build.lib.analysis.config.BuildConfiguration; import com.google.devtools.build.lib.cmdline.Label; import com.google.devtools.build.lib.collect.nestedset.NestedSet; import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; import com.google.devtools.build.lib.packages.AspectDefinition; import com.google.devtools.build.lib.packages.AspectParameters; import com.google.devtools.build.lib.packages.Attribute; -import com.google.devtools.build.lib.packages.AttributeMap; import com.google.devtools.build.lib.packages.NativeAspectClass; -import com.google.devtools.build.lib.packages.Rule; import com.google.devtools.build.lib.packages.RuleClass.ConfiguredTargetFactory.RuleErrorException; import com.google.devtools.build.lib.rules.cpp.CcCommon; import com.google.devtools.build.lib.rules.cpp.CcLibraryHelper; @@ -71,21 +68,17 @@ public class CcProtoAspect extends NativeAspectClass implements ConfiguredAspect private static final String PROTO_TOOLCHAIN_ATTR = ":aspect_cc_proto_toolchain"; - private static final Attribute.LateBoundLabel<BuildConfiguration> PROTO_TOOLCHAIN_LABEL = - new Attribute.LateBoundLabel<BuildConfiguration>( - "@com_google_protobuf_cc//:cc_toolchain", ProtoConfiguration.class) { - @Override - public Label resolve(Rule rule, AttributeMap attributes, BuildConfiguration configuration) { - return configuration.getFragment(ProtoConfiguration.class).protoToolchainForCc(); - } - }; + private static final Attribute.LateBoundDefault<?, Label> PROTO_TOOLCHAIN_LABEL = + Attribute.LateBoundDefault.fromTargetConfiguration( + ProtoConfiguration.class, + Label.parseAbsoluteUnchecked("@com_google_protobuf_cc//:cc_toolchain"), + (rule, attributes, protoConfig) -> protoConfig.protoToolchainForCc()); private final CppSemantics cppSemantics; - private final Attribute.LateBoundLabel<BuildConfiguration> ccToolchainAttrValue; + private final Attribute.LateBoundDefault<?, Label> ccToolchainAttrValue; public CcProtoAspect( - CppSemantics cppSemantics, - Attribute.LateBoundLabel<BuildConfiguration> ccToolchainAttrValue) { + CppSemantics cppSemantics, Attribute.LateBoundDefault<?, Label> ccToolchainAttrValue) { this.cppSemantics = cppSemantics; this.ccToolchainAttrValue = ccToolchainAttrValue; } diff --git a/src/main/java/com/google/devtools/build/lib/rules/genrule/GenRuleBaseRule.java b/src/main/java/com/google/devtools/build/lib/rules/genrule/GenRuleBaseRule.java index 67e5a6f8b7..1bd75edd74 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/genrule/GenRuleBaseRule.java +++ b/src/main/java/com/google/devtools/build/lib/rules/genrule/GenRuleBaseRule.java @@ -25,13 +25,12 @@ import com.google.devtools.build.lib.analysis.BaseRuleClasses; import com.google.devtools.build.lib.analysis.MakeVariableInfo; import com.google.devtools.build.lib.analysis.RuleDefinition; import com.google.devtools.build.lib.analysis.RuleDefinitionEnvironment; -import com.google.devtools.build.lib.analysis.config.BuildConfiguration; import com.google.devtools.build.lib.cmdline.Label; import com.google.devtools.build.lib.packages.Attribute; -import com.google.devtools.build.lib.packages.Attribute.LateBoundLabel; +import com.google.devtools.build.lib.packages.Attribute.ComputedDefault; +import com.google.devtools.build.lib.packages.Attribute.LateBoundDefault; 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.RuleClass; import com.google.devtools.build.lib.packages.RuleClass.Builder.RuleClassType; import com.google.devtools.build.lib.rules.cpp.CppConfiguration; @@ -50,29 +49,25 @@ public class GenRuleBaseRule implements RuleDefinition { * Late-bound dependency on the C++ toolchain <i>iff</i> the genrule has make variables that need * that toolchain. */ - public static Attribute.LateBoundLabel<BuildConfiguration> ccToolchainAttribute( - RuleDefinitionEnvironment env) { - return new LateBoundLabel<BuildConfiguration>( - env.getToolsLabel(CppRuleClasses.CROSSTOOL_LABEL), CppConfiguration.class) { - @Override - public Label resolve(Rule rule, AttributeMap attributes, BuildConfiguration configuration) { - return attributes != null - && GenRuleBase.requiresCrosstool(attributes.get("cmd", Type.STRING)) - ? CppRuleClasses.ccToolchainAttribute(env).resolve(rule, attributes, configuration) - : null; - } - }; + public static LateBoundDefault<?, Label> ccToolchainAttribute(RuleDefinitionEnvironment env) { + return LateBoundDefault.fromTargetConfiguration( + CppConfiguration.class, + env.getToolsLabel(CppRuleClasses.CROSSTOOL_LABEL), + // null guards are needed for LateBoundAttributeTest + (rule, attributes, cppConfig) -> + attributes != null + && attributes.get("cmd", Type.STRING) != null + && GenRuleBase.requiresCrosstool(attributes.get("cmd", Type.STRING)) + ? CppRuleClasses.ccToolchainAttribute(env).resolve(rule, attributes, cppConfig) + : null); } - /** Late-bound dependency on the C++ toolchain type. */ - public static Attribute.LateBoundLabel<BuildConfiguration> ccToolchainTypeAttribute( - RuleDefinitionEnvironment env) { - return new LateBoundLabel<BuildConfiguration>( - env.getToolsLabel(CppHelper.TOOLCHAIN_TYPE_LABEL), CppConfiguration.class) { + /** Computed dependency on the C++ toolchain type. */ + public static ComputedDefault ccToolchainTypeAttribute(RuleDefinitionEnvironment env) { + return new ComputedDefault("cmd") { @Override - public Label resolve(Rule rule, AttributeMap attributes, BuildConfiguration configuration) { - return attributes != null - && GenRuleBase.requiresCrosstool(attributes.get("cmd", Type.STRING)) + public Object getDefault(AttributeMap rule) { + return GenRuleBase.requiresCrosstool(rule.get("cmd", Type.STRING)) ? CppHelper.getCcToolchainType(env.getToolsRepository()) : null; } diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaSemantics.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaSemantics.java index f83d0fe82e..ca43c7e92e 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaSemantics.java +++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaSemantics.java @@ -35,11 +35,8 @@ import com.google.devtools.build.lib.analysis.config.BuildConfiguration; import com.google.devtools.build.lib.cmdline.Label; import com.google.devtools.build.lib.collect.nestedset.NestedSet; import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; -import com.google.devtools.build.lib.packages.Attribute.LateBoundLabel; -import com.google.devtools.build.lib.packages.Attribute.LateBoundLabelList; -import com.google.devtools.build.lib.packages.AttributeMap; +import com.google.devtools.build.lib.packages.Attribute.LateBoundDefault; import com.google.devtools.build.lib.packages.ImplicitOutputsFunction.SafeImplicitOutputsFunction; -import com.google.devtools.build.lib.packages.Rule; import com.google.devtools.build.lib.rules.java.DeployArchiveBuilder.Compression; import com.google.devtools.build.lib.rules.java.JavaCompilationArgs.ClasspathType; import com.google.devtools.build.lib.rules.java.JavaConfiguration.JavaOptimizationMode; @@ -112,14 +109,11 @@ public interface JavaSemantics { /** The java_toolchain.compatible_javacopts key for proto compilations. */ public static final String PROTO_JAVACOPTS_KEY = "proto"; - LateBoundLabel<BuildConfiguration> JAVA_TOOLCHAIN = - new LateBoundLabel<BuildConfiguration>(JAVA_TOOLCHAIN_LABEL, JavaConfiguration.class) { - @Override - public Label resolve(Rule rule, AttributeMap attributes, - BuildConfiguration configuration) { - return configuration.getFragment(JavaConfiguration.class).getToolchainLabel(); - } - }; + LateBoundDefault<?, Label> JAVA_TOOLCHAIN = + LateBoundDefault.fromTargetConfiguration( + JavaConfiguration.class, + Label.parseAbsoluteUnchecked(JAVA_TOOLCHAIN_LABEL), + (rule, attributes, javaConfig) -> javaConfig.getToolchainLabel()); /** * Name of the output group used for source jars. @@ -135,111 +129,86 @@ public interface JavaSemantics { OutputGroupProvider.HIDDEN_OUTPUT_GROUP_PREFIX + "gen_jars"; /** Implementation for the :jvm attribute. */ - static LateBoundLabel<BuildConfiguration> jvmAttribute(RuleDefinitionEnvironment env) { - return new LateBoundLabel<BuildConfiguration>( - env.getToolsLabel(JavaImplicitAttributes.JDK_LABEL), Jvm.class) { - @Override - public Label resolve(Rule rule, AttributeMap attributes, BuildConfiguration configuration) { - return configuration.getFragment(Jvm.class).getJvmLabel(); - } - }; + static LateBoundDefault<?, Label> jvmAttribute(RuleDefinitionEnvironment env) { + return LateBoundDefault.fromTargetConfiguration( + Jvm.class, + env.getToolsLabel(JavaImplicitAttributes.JDK_LABEL), + (rule, attributes, jvm) -> jvm.getJvmLabel()); } /** Implementation for the :host_jdk attribute. */ - static LateBoundLabel<BuildConfiguration> hostJdkAttribute(RuleDefinitionEnvironment env) { - return new LateBoundLabel<BuildConfiguration>( - env.getToolsLabel(JavaImplicitAttributes.JDK_LABEL), Jvm.class) { - @Override - public boolean useHostConfiguration() { - return true; - } - - @Override - public Label resolve(Rule rule, AttributeMap attributes, BuildConfiguration configuration) { - return configuration.getFragment(Jvm.class).getJvmLabel(); - } - }; + static LateBoundDefault<?, Label> hostJdkAttribute(RuleDefinitionEnvironment env) { + return LateBoundDefault.fromHostConfiguration( + Jvm.class, + env.getToolsLabel(JavaImplicitAttributes.JDK_LABEL), + (rule, attributes, jvm) -> jvm.getJvmLabel()); } /** * Implementation for the :java_launcher attribute. Note that the Java launcher is disabled by * default, so it returns null for the configuration-independent default value. */ - LateBoundLabel<BuildConfiguration> JAVA_LAUNCHER = - new LateBoundLabel<BuildConfiguration>(JavaConfiguration.class) { - @Override - public Label resolve(Rule rule, AttributeMap attributes, BuildConfiguration configuration) { - // This nullness check is purely for the sake of a test that doesn't bother to include an - // attribute map when calling this method. - if (attributes != null) { - // Don't depend on the launcher if we don't create an executable anyway - if (attributes.has("create_executable") - && !attributes.get("create_executable", Type.BOOLEAN)) { - return null; + LateBoundDefault<?, Label> JAVA_LAUNCHER = + LateBoundDefault.fromTargetConfiguration( + JavaConfiguration.class, + null, + (rule, attributes, javaConfig) -> { + // This nullness check is purely for the sake of a test that doesn't bother to include + // an + // attribute map when calling this method. + if (attributes != null) { + // Don't depend on the launcher if we don't create an executable anyway + if (attributes.has("create_executable") + && !attributes.get("create_executable", Type.BOOLEAN)) { + return null; + } + + // don't read --java_launcher if this target overrides via a launcher attribute + if (attributes.isAttributeValueExplicitlySpecified("launcher")) { + return attributes.get("launcher", LABEL); + } } - - // don't read --java_launcher if this target overrides via a launcher attribute - if (attributes.isAttributeValueExplicitlySpecified("launcher")) { - return attributes.get("launcher", LABEL); + return javaConfig.getJavaLauncherLabel(); + }); + + // TODO(b/65746853): provide a way to do this without passing the entire configuration + LateBoundDefault<?, List<Label>> JAVA_PLUGINS = + LateBoundDefault.fromTargetConfiguration( + BuildConfiguration.class, + ImmutableList.of(), + (rule, attributes, configuration) -> ImmutableList.copyOf(configuration.getPlugins())); + + /** Implementation for the :proguard attribute. */ + LateBoundDefault<?, Label> PROGUARD = + LateBoundDefault.fromTargetConfiguration( + JavaConfiguration.class, + null, + (rule, attributes, javaConfig) -> javaConfig.getProguardBinary()); + + LateBoundDefault<?, List<Label>> EXTRA_PROGUARD_SPECS = + LateBoundDefault.fromTargetConfiguration( + JavaConfiguration.class, + ImmutableList.of(), + (rule, attributes, javaConfig) -> + ImmutableList.copyOf(javaConfig.getExtraProguardSpecs())); + + LateBoundDefault<?, List<Label>> BYTECODE_OPTIMIZERS = + LateBoundDefault.fromTargetConfiguration( + JavaConfiguration.class, + ImmutableList.of(), + (rule, attributes, javaConfig) -> { + // Use a modicum of smarts to avoid implicit dependencies where we don't need them. + JavaOptimizationMode optMode = javaConfig.getJavaOptimizationMode(); + boolean hasProguardSpecs = + attributes.has("proguard_specs") + && !attributes.get("proguard_specs", LABEL_LIST).isEmpty(); + if (optMode == JavaOptimizationMode.NOOP + || (optMode == JavaOptimizationMode.LEGACY && !hasProguardSpecs)) { + return ImmutableList.<Label>of(); } - } - return configuration.getFragment(JavaConfiguration.class).getJavaLauncherLabel(); - } - }; - - LateBoundLabelList<BuildConfiguration> JAVA_PLUGINS = - new LateBoundLabelList<BuildConfiguration>() { - @Override - public List<Label> resolve(Rule rule, AttributeMap attributes, - BuildConfiguration configuration) { - return ImmutableList.copyOf(configuration.getPlugins()); - } - }; - - /** - * Implementation for the :proguard attribute. - */ - LateBoundLabel<BuildConfiguration> PROGUARD = - new LateBoundLabel<BuildConfiguration>(JavaConfiguration.class) { - @Override - public Label resolve(Rule rule, AttributeMap attributes, - BuildConfiguration configuration) { - return configuration.getFragment(JavaConfiguration.class).getProguardBinary(); - } - }; - - LateBoundLabelList<BuildConfiguration> EXTRA_PROGUARD_SPECS = - new LateBoundLabelList<BuildConfiguration>() { - @Override - public List<Label> resolve(Rule rule, AttributeMap attributes, - BuildConfiguration configuration) { - return ImmutableList.copyOf( - configuration.getFragment(JavaConfiguration.class).getExtraProguardSpecs()); - } - }; - - LateBoundLabelList<BuildConfiguration> BYTECODE_OPTIMIZERS = - new LateBoundLabelList<BuildConfiguration>(JavaConfiguration.class) { - @Override - public List<Label> resolve( - Rule rule, AttributeMap attributes, BuildConfiguration configuration) { - // Use a modicum of smarts to avoid implicit dependencies where we don't need them. - JavaOptimizationMode optMode = - configuration.getFragment(JavaConfiguration.class).getJavaOptimizationMode(); - boolean hasProguardSpecs = attributes.has("proguard_specs") - && !attributes.get("proguard_specs", LABEL_LIST).isEmpty(); - if (optMode == JavaOptimizationMode.NOOP - || (optMode == JavaOptimizationMode.LEGACY && !hasProguardSpecs)) { - return ImmutableList.<Label>of(); - } - return ImmutableList.copyOf( - Optional.presentInstances( - configuration - .getFragment(JavaConfiguration.class) - .getBytecodeOptimizers() - .values())); - } - }; + return ImmutableList.copyOf( + Optional.presentInstances(javaConfig.getBytecodeOptimizers().values())); + }); String IJAR_LABEL = "//tools/defaults:ijar"; diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/proto/JavaLiteProtoAspect.java b/src/main/java/com/google/devtools/build/lib/rules/java/proto/JavaLiteProtoAspect.java index fbf667e4d8..9b09be1b1a 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/java/proto/JavaLiteProtoAspect.java +++ b/src/main/java/com/google/devtools/build/lib/rules/java/proto/JavaLiteProtoAspect.java @@ -35,7 +35,6 @@ import com.google.devtools.build.lib.analysis.TransitiveInfoProvider; import com.google.devtools.build.lib.analysis.TransitiveInfoProviderMap; import com.google.devtools.build.lib.analysis.TransitiveInfoProviderMapBuilder; import com.google.devtools.build.lib.analysis.WrappingProvider; -import com.google.devtools.build.lib.analysis.config.BuildConfiguration; import com.google.devtools.build.lib.analysis.config.BuildConfiguration.StrictDepsMode; import com.google.devtools.build.lib.analysis.configuredtargets.RuleConfiguredTarget; import com.google.devtools.build.lib.cmdline.Label; @@ -45,10 +44,8 @@ import com.google.devtools.build.lib.collect.nestedset.Order; import com.google.devtools.build.lib.packages.AspectDefinition; import com.google.devtools.build.lib.packages.AspectParameters; import com.google.devtools.build.lib.packages.Attribute; -import com.google.devtools.build.lib.packages.Attribute.LateBoundLabel; -import com.google.devtools.build.lib.packages.AttributeMap; +import com.google.devtools.build.lib.packages.Attribute.LateBoundDefault; import com.google.devtools.build.lib.packages.NativeAspectClass; -import com.google.devtools.build.lib.packages.Rule; import com.google.devtools.build.lib.rules.java.JavaCompilationArgsProvider; import com.google.devtools.build.lib.rules.java.JavaCompilationArtifacts; import com.google.devtools.build.lib.rules.java.JavaCompilationHelper; @@ -72,28 +69,24 @@ public class JavaLiteProtoAspect extends NativeAspectClass implements Configured public static final String PROTO_TOOLCHAIN_ATTR = ":aspect_proto_toolchain_for_javalite"; - public static Attribute.LateBoundLabel<BuildConfiguration> getProtoToolchainLabel( - String defaultValue) { - return new Attribute.LateBoundLabel<BuildConfiguration>( - defaultValue, ProtoConfiguration.class) { - @Override - public Label resolve(Rule rule, AttributeMap attributes, BuildConfiguration configuration) { - return configuration.getFragment(ProtoConfiguration.class).protoToolchainForJavaLite(); - } - }; + public static LateBoundDefault<?, Label> getProtoToolchainLabel(String defaultValue) { + return LateBoundDefault.fromTargetConfiguration( + ProtoConfiguration.class, + Label.parseAbsoluteUnchecked(defaultValue), + (rule, attributes, protoConfig) -> protoConfig.protoToolchainForJavaLite()); } private final JavaSemantics javaSemantics; @Nullable private final String jacocoLabel; private final String defaultProtoToolchainLabel; - private final LateBoundLabel<BuildConfiguration> hostJdkAttribute; + private final LateBoundDefault<?, Label> hostJdkAttribute; public JavaLiteProtoAspect( JavaSemantics javaSemantics, @Nullable String jacocoLabel, String defaultProtoToolchainLabel, - LateBoundLabel<BuildConfiguration> hostJdkAttribute) { + LateBoundDefault<?, Label> hostJdkAttribute) { this.javaSemantics = javaSemantics; this.jacocoLabel = jacocoLabel; this.defaultProtoToolchainLabel = defaultProtoToolchainLabel; diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/proto/JavaProtoAspect.java b/src/main/java/com/google/devtools/build/lib/rules/java/proto/JavaProtoAspect.java index ec843a00d8..91e4b3b734 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/java/proto/JavaProtoAspect.java +++ b/src/main/java/com/google/devtools/build/lib/rules/java/proto/JavaProtoAspect.java @@ -34,7 +34,6 @@ import com.google.devtools.build.lib.analysis.TransitiveInfoCollection; import com.google.devtools.build.lib.analysis.TransitiveInfoProviderMap; import com.google.devtools.build.lib.analysis.TransitiveInfoProviderMapBuilder; import com.google.devtools.build.lib.analysis.WrappingProvider; -import com.google.devtools.build.lib.analysis.config.BuildConfiguration; import com.google.devtools.build.lib.analysis.config.BuildConfiguration.StrictDepsMode; import com.google.devtools.build.lib.analysis.configuredtargets.RuleConfiguredTarget; import com.google.devtools.build.lib.cmdline.Label; @@ -44,10 +43,8 @@ import com.google.devtools.build.lib.collect.nestedset.Order; import com.google.devtools.build.lib.packages.AspectDefinition; import com.google.devtools.build.lib.packages.AspectParameters; import com.google.devtools.build.lib.packages.Attribute; -import com.google.devtools.build.lib.packages.Attribute.LateBoundLabel; -import com.google.devtools.build.lib.packages.AttributeMap; +import com.google.devtools.build.lib.packages.Attribute.LateBoundDefault; import com.google.devtools.build.lib.packages.NativeAspectClass; -import com.google.devtools.build.lib.packages.Rule; import com.google.devtools.build.lib.rules.java.JavaCompilationArgsProvider; import com.google.devtools.build.lib.rules.java.JavaCompilationHelper; import com.google.devtools.build.lib.rules.java.JavaConfiguration; @@ -71,17 +68,13 @@ import javax.annotation.Nullable; public class JavaProtoAspect extends NativeAspectClass implements ConfiguredAspectFactory { private static final String SPEED_PROTO_TOOLCHAIN_ATTR = ":aspect_java_proto_toolchain"; - private final LateBoundLabel<BuildConfiguration> hostJdkAttribute; - - private static Attribute.LateBoundLabel<BuildConfiguration> getSpeedProtoToolchainLabel( - String defaultValue) { - return new Attribute.LateBoundLabel<BuildConfiguration>( - defaultValue, ProtoConfiguration.class) { - @Override - public Label resolve(Rule rule, AttributeMap attributes, BuildConfiguration configuration) { - return configuration.getFragment(ProtoConfiguration.class).protoToolchainForJava(); - } - }; + private final LateBoundDefault<?, Label> hostJdkAttribute; + + private static LateBoundDefault<?, Label> getSpeedProtoToolchainLabel(String defaultValue) { + return LateBoundDefault.fromTargetConfiguration( + ProtoConfiguration.class, + Label.parseAbsoluteUnchecked(defaultValue), + (rule, attributes, protoConfig) -> protoConfig.protoToolchainForJava()); } private final JavaSemantics javaSemantics; @@ -95,7 +88,7 @@ public class JavaProtoAspect extends NativeAspectClass implements ConfiguredAspe @Nullable String jacocoLabel, RpcSupport rpcSupport, String defaultSpeedProtoToolchainLabel, - LateBoundLabel<BuildConfiguration> hostJdkAttribute) { + LateBoundDefault<?, Label> hostJdkAttribute) { this.javaSemantics = javaSemantics; this.jacocoLabel = jacocoLabel; this.rpcSupport = rpcSupport; diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/IosTestRule.java b/src/main/java/com/google/devtools/build/lib/rules/objc/IosTestRule.java index 78aaba6988..d5d5851072 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/IosTestRule.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/IosTestRule.java @@ -27,9 +27,8 @@ import com.google.devtools.build.lib.analysis.RuleDefinitionEnvironment; import com.google.devtools.build.lib.analysis.config.BuildConfiguration; import com.google.devtools.build.lib.cmdline.Label; import com.google.devtools.build.lib.packages.Attribute.ComputedDefault; -import com.google.devtools.build.lib.packages.Attribute.LateBoundLabel; +import com.google.devtools.build.lib.packages.Attribute.LateBoundDefault; import com.google.devtools.build.lib.packages.AttributeMap; -import com.google.devtools.build.lib.packages.Rule; import com.google.devtools.build.lib.packages.RuleClass; import com.google.devtools.build.lib.packages.RuleClass.Builder.RuleClassType; import com.google.devtools.build.lib.rules.apple.AppleConfiguration; @@ -140,21 +139,16 @@ public class IosTestRule implements RuleDefinition { attr(IosTest.OBJC_GCOV_ATTR, LABEL) .cfg(HOST) .value(env.getToolsLabel("//tools/objc:gcov"))) + // TODO(b/65746853): provide a way to do this without passing the entire configuration .add( attr(IosTest.MCOV_TOOL_ATTR, LABEL) .cfg(HOST) .value( - new LateBoundLabel<BuildConfiguration>(mcov) { - @Override - public Label resolve( - Rule rule, AttributeMap attributes, BuildConfiguration configuration) { - if (!configuration.isCodeCoverageEnabled()) { - return null; - } - - return mcov; - } - })) + LateBoundDefault.fromTargetConfiguration( + BuildConfiguration.class, + mcov, + (rule, attributes, configuration) -> + configuration.isCodeCoverageEnabled() ? mcov : null))) .cfg(AppleCrosstoolTransition.APPLE_CROSSTOOL_TRANSITION) .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 016ec5c091..87c24ab678 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 @@ -37,18 +37,15 @@ 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.BuildConfiguration; 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; import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; import com.google.devtools.build.lib.packages.AspectDefinition; import com.google.devtools.build.lib.packages.AspectParameters; -import com.google.devtools.build.lib.packages.Attribute.LateBoundLabel; -import com.google.devtools.build.lib.packages.AttributeMap; +import com.google.devtools.build.lib.packages.Attribute.LateBoundDefault; import com.google.devtools.build.lib.packages.BuildType; import com.google.devtools.build.lib.packages.NativeAspectClass; -import com.google.devtools.build.lib.packages.Rule; import com.google.devtools.build.lib.packages.RuleClass.ConfiguredTargetFactory.RuleErrorException; import com.google.devtools.build.lib.rules.apple.AppleConfiguration; import com.google.devtools.build.lib.rules.apple.AppleToolchain; @@ -105,13 +102,11 @@ public class J2ObjcAspect extends NativeAspectClass implements ConfiguredAspectF protected static final ImmutableList<String> J2OBJC_PLUGIN_PARAMS = ImmutableList.of("file_dir_mapping", "generate_class_mappings"); - private static final LateBoundLabel<BuildConfiguration> DEAD_CODE_REPORT = - new LateBoundLabel<BuildConfiguration>(J2ObjcConfiguration.class) { - @Override - public Label resolve(Rule rule, AttributeMap attributes, BuildConfiguration configuration) { - return configuration.getFragment(J2ObjcConfiguration.class).deadCodeReport().orNull(); - } - }; + private static final LateBoundDefault<?, Label> DEAD_CODE_REPORT = + LateBoundDefault.fromTargetConfiguration( + J2ObjcConfiguration.class, + null, + (rule, attributes, j2objcConfig) -> j2objcConfig.deadCodeReport().orNull()); /** Adds additional attribute aspects and attributes to the given AspectDefinition.Builder. */ protected AspectDefinition.Builder addAdditionalAttributes(AspectDefinition.Builder builder) { @@ -182,14 +177,12 @@ public class J2ObjcAspect extends NativeAspectClass implements ConfiguredAspectF .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(HOST) - .value(DEAD_CODE_REPORT)) - .add(attr("$jre_lib", LABEL) - .value( - Label.parseAbsoluteUnchecked( - toolsRepository + "//third_party/java/j2objc:jre_core_lib"))) + attr("$jre_lib", LABEL) + .value( + Label.parseAbsoluteUnchecked( + toolsRepository + "//third_party/java/j2objc:jre_core_lib"))) .add( attr("$protobuf_lib", LABEL) .value( @@ -210,7 +203,7 @@ public class J2ObjcAspect extends NativeAspectClass implements ConfiguredAspectF .allowedRuleClasses("xcode_config") .checkConstraints() .direct_compile_time_input() - .value(new AppleToolchain.XcodeConfigLabel(toolsRepository))) + .value(AppleToolchain.getXcodeConfigLabel(toolsRepository))) .add( attr("$zipper", LABEL) .cfg(HOST) @@ -224,8 +217,12 @@ public class J2ObjcAspect extends NativeAspectClass implements ConfiguredAspectF toolsRepository + "//tools/j2objc:j2objc_proto_blacklist")))) .add(attr(":j2objc_cc_toolchain", LABEL).value(ObjcRuleClasses.APPLE_TOOLCHAIN)) .add( + // Objc builds do not use a lipo context collector, but must specify the attribute as + // a late-bound attribute to match with the similar attribute on the cc rules. + // TODO(b/28084560): Allow :lipo_context_collector not to be set instead of having a + // null instance. attr(":lipo_context_collector", LABEL) - .value(ObjcRuleClasses.NULL_LIPO_CONTEXT_COLLECTOR) + .value(LateBoundDefault.alwaysNull()) .skipPrereqValidatorCheck()) .build(); } diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcRuleClasses.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcRuleClasses.java index 2fee1f098f..56c7ae505b 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcRuleClasses.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcRuleClasses.java @@ -41,11 +41,10 @@ import com.google.devtools.build.lib.analysis.config.BuildConfiguration; import com.google.devtools.build.lib.cmdline.Label; import com.google.devtools.build.lib.collect.nestedset.NestedSet; import com.google.devtools.build.lib.packages.Attribute; -import com.google.devtools.build.lib.packages.Attribute.LateBoundLabel; +import com.google.devtools.build.lib.packages.Attribute.LateBoundDefault; import com.google.devtools.build.lib.packages.AttributeMap; import com.google.devtools.build.lib.packages.BuildType; import com.google.devtools.build.lib.packages.ImplicitOutputsFunction.SafeImplicitOutputsFunction; -import com.google.devtools.build.lib.packages.Rule; import com.google.devtools.build.lib.packages.RuleClass; import com.google.devtools.build.lib.packages.RuleClass.Builder; import com.google.devtools.build.lib.packages.RuleClass.Builder.RuleClassType; @@ -160,30 +159,13 @@ public class ObjcRuleClasses { /** * Late-bound attribute giving the CcToolchain for CROSSTOOL_LABEL. * - * TODO(cpeyser): Use AppleCcToolchain instead of CcToolchain once released. + * <p>TODO(cpeyser): Use AppleCcToolchain instead of CcToolchain once released. */ - public static final LateBoundLabel<BuildConfiguration> APPLE_TOOLCHAIN = - new LateBoundLabel<BuildConfiguration>(CROSSTOOL_LABEL, CppConfiguration.class) { - @Override - public Label resolve( - Rule rule, AttributeMap attributes, BuildConfiguration configuration) { - return configuration.getFragment(CppConfiguration.class).getCcToolchainRuleLabel(); - } - }; - - /** - * A null value for the lipo context collector. Objc builds do not use a lipo context collector. - */ - // TODO(b/28084560): Allow :lipo_context_collector not to be set instead of having a null - // instance. - public static final LateBoundLabel<BuildConfiguration> NULL_LIPO_CONTEXT_COLLECTOR = - new LateBoundLabel<BuildConfiguration>() { - @Override - public Label resolve( - Rule rule, AttributeMap attributes, BuildConfiguration configuration) { - return null; - } - }; + public static final LateBoundDefault<?, Label> APPLE_TOOLCHAIN = + LateBoundDefault.fromTargetConfiguration( + CppConfiguration.class, + Label.parseAbsoluteUnchecked(CROSSTOOL_LABEL), + (rule, attributes, cppConfig) -> cppConfig.getCcToolchainRuleLabel()); /** * Creates a new spawn action builder with apple environment variables set that are typically @@ -543,8 +525,12 @@ public class ObjcRuleClasses { attr(CcToolchain.CC_TOOLCHAIN_TYPE_ATTRIBUTE_NAME, LABEL) .value(CppRuleClasses.ccToolchainTypeAttribute(env))) .add( + // Objc builds do not use a lipo context collector, but must specify the attribute as + // a late-bound attribute to match with the similar attribute on the cc rules. + // TODO(b/28084560): Allow :lipo_context_collector not to be set instead of having a + // null instance. attr(":lipo_context_collector", LABEL) - .value(NULL_LIPO_CONTEXT_COLLECTOR) + .value(LateBoundDefault.alwaysNull()) .skipPrereqValidatorCheck()) .build(); } @@ -677,7 +663,7 @@ public class ObjcRuleClasses { .direct_compile_time_input() .allowedRuleClasses(ALLOWED_CC_DEPS_RULE_CLASSES) .mandatoryProviders(ObjcProvider.SKYLARK_CONSTRUCTOR.id()) - .allowedFileTypes()) + .allowedFileTypes()) /* <!-- #BLAZE_RULE($objc_compiling_rule).ATTRIBUTE(runtime_deps) --> The list of framework targets that are late loaded at runtime. They are included in the app bundle but not linked against at build time. @@ -721,9 +707,7 @@ public class ObjcRuleClasses { If specified, Bazel will not generate a module map for this target, but will pass the provided module map to the compiler. <!-- #END_BLAZE_RULE.ATTRIBUTE -->*/ - .add( - attr("module_map", LABEL) - .allowedFileTypes(FileType.of(".modulemap"))) + .add(attr("module_map", LABEL).allowedFileTypes(FileType.of(".modulemap"))) /* Provides the label for header_scanner tool that is used to scan inclusions for ObjC sources and provide a list of required headers via a .header_list file. @@ -735,33 +719,21 @@ public class ObjcRuleClasses { attr(HEADER_SCANNER_ATTRIBUTE, LABEL) .cfg(HOST) .value( - new LateBoundLabel<BuildConfiguration>( + LateBoundDefault.fromTargetConfiguration( + ObjcConfiguration.class, env.getToolsLabel("//tools/objc:header_scanner"), - ObjcConfiguration.class) { - @Override - public Label resolve( - Rule rule, AttributeMap attributes, BuildConfiguration configuration) { - return configuration - .getFragment(ObjcConfiguration.class) - .getObjcHeaderScannerTool(); - } - })) + (rule, attributes, objcConfig) -> objcConfig.getObjcHeaderScannerTool()))) .add( attr(APPLE_SDK_ATTRIBUTE, LABEL) .value( - new LateBoundLabel<BuildConfiguration>(ObjcConfiguration.class) { - @Override - public Label resolve( - Rule rule, AttributeMap attributes, BuildConfiguration configuration) { - ObjcConfiguration objcConfiguration = - configuration.getFragment(ObjcConfiguration.class); + LateBoundDefault.fromTargetConfiguration( + ObjcConfiguration.class, + null, // Apple SDKs are currently only used by ObjC header thinning feature - if (objcConfiguration.useExperimentalHeaderThinning()) { - return objcConfiguration.getAppleSdk(); - } - return null; - } - })) + (rule, attributes, objcConfig) -> + objcConfig.useExperimentalHeaderThinning() + ? objcConfig.getAppleSdk() + : null))) .build(); } @Override @@ -1191,15 +1163,10 @@ public class ObjcRuleClasses { .singleArtifact() .cfg(HOST) .value( - new LateBoundLabel<BuildConfiguration>(ObjcConfiguration.class) { - @Override - public Label resolve( - Rule rule, AttributeMap attributes, BuildConfiguration configuration) { - return configuration - .getFragment(ObjcConfiguration.class) - .getExtraEntitlements(); - } - }) + LateBoundDefault.fromTargetConfiguration( + ObjcConfiguration.class, + null, + (rule, attributes, objcConfig) -> objcConfig.getExtraEntitlements())) .allowedFileTypes(ENTITLEMENTS_TYPE)) .add( attr(DEBUG_ENTITLEMENTS_ATTR, LABEL) @@ -1222,22 +1189,20 @@ public class ObjcRuleClasses { .singleArtifact() .allowedFileTypes(FileType.of(".mobileprovision")) .value( - new LateBoundLabel<BuildConfiguration>(ObjcConfiguration.class) { - @Override - public Label resolve( - Rule rule, AttributeMap attributes, BuildConfiguration configuration) { - AppleConfiguration appleConfiguration = - configuration.getFragment(AppleConfiguration.class); - if (appleConfiguration.getMultiArchPlatform(PlatformType.IOS) - != ApplePlatform.IOS_DEVICE) { - return null; - } - if (rule.isAttributeValueExplicitlySpecified(PROVISIONING_PROFILE_ATTR)) { - return null; - } - return appleConfiguration.getDefaultProvisioningProfileLabel(); - } - })) + LateBoundDefault.fromTargetConfiguration( + AppleConfiguration.class, + null, + (rule, attributes, appleConfig) -> { + if (appleConfig.getMultiArchPlatform(PlatformType.IOS) + != ApplePlatform.IOS_DEVICE) { + return null; + } + if (attributes.isAttributeValueExplicitlySpecified( + PROVISIONING_PROFILE_ATTR)) { + return null; + } + return appleConfig.getDefaultProvisioningProfileLabel(); + }))) /* <!-- #BLAZE_RULE($objc_release_bundling_rule).ATTRIBUTE(app_icon) --> The name of the application icon. @@ -1507,23 +1472,20 @@ public class ObjcRuleClasses { .singleArtifact() .allowedFileTypes(FileType.of(".mobileprovision")) .value( - new LateBoundLabel<BuildConfiguration>(ObjcConfiguration.class) { - @Override - public Label resolve( - Rule rule, AttributeMap attributes, BuildConfiguration configuration) { - AppleConfiguration appleConfiguration = - configuration.getFragment(AppleConfiguration.class); - if (appleConfiguration.getMultiArchPlatform(PlatformType.IOS) - != ApplePlatform.IOS_DEVICE) { - return null; - } - if (rule.isAttributeValueExplicitlySpecified( - WATCH_EXT_PROVISIONING_PROFILE_ATTR)) { - return null; - } - return appleConfiguration.getDefaultProvisioningProfileLabel(); - } - })) + LateBoundDefault.fromTargetConfiguration( + AppleConfiguration.class, + null, + (rule, attributes, appleConfig) -> { + if (appleConfig.getMultiArchPlatform(PlatformType.IOS) + != ApplePlatform.IOS_DEVICE) { + return null; + } + if (attributes.isAttributeValueExplicitlySpecified( + WATCH_EXT_PROVISIONING_PROFILE_ATTR)) { + return null; + } + return appleConfig.getDefaultProvisioningProfileLabel(); + }))) /* <!-- #BLAZE_RULE($watch_extension_bundle_rule).ATTRIBUTE(ext_resources) --> Files to include in the final watch extension bundle. @@ -1696,23 +1658,20 @@ public class ObjcRuleClasses { .singleArtifact() .allowedFileTypes(FileType.of(".mobileprovision")) .value( - new LateBoundLabel<BuildConfiguration>(ObjcConfiguration.class) { - @Override - public Label resolve( - Rule rule, AttributeMap attributes, BuildConfiguration configuration) { - AppleConfiguration appleConfiguration = - configuration.getFragment(AppleConfiguration.class); - if (appleConfiguration.getMultiArchPlatform(PlatformType.IOS) - != ApplePlatform.IOS_DEVICE) { - return null; - } - if (rule.isAttributeValueExplicitlySpecified( - WATCH_APP_PROVISIONING_PROFILE_ATTR)) { - return null; - } - return appleConfiguration.getDefaultProvisioningProfileLabel(); - } - })) + LateBoundDefault.fromTargetConfiguration( + AppleConfiguration.class, + null, + (rule, attributes, appleConfig) -> { + if (appleConfig.getMultiArchPlatform(PlatformType.IOS) + != ApplePlatform.IOS_DEVICE) { + return null; + } + if (attributes.isAttributeValueExplicitlySpecified( + WATCH_APP_PROVISIONING_PROFILE_ATTR)) { + return null; + } + return appleConfig.getDefaultProvisioningProfileLabel(); + }))) /* <!-- #BLAZE_RULE($objc_resources_rule).ATTRIBUTE(app_storyboards) --> Files which are .storyboard resources for the watch application, possibly localizable. diff --git a/src/main/java/com/google/devtools/build/lib/rules/proto/BazelProtoLibraryRule.java b/src/main/java/com/google/devtools/build/lib/rules/proto/BazelProtoLibraryRule.java index 168f82f415..e7891c4eb2 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/proto/BazelProtoLibraryRule.java +++ b/src/main/java/com/google/devtools/build/lib/rules/proto/BazelProtoLibraryRule.java @@ -22,11 +22,8 @@ import static com.google.devtools.build.lib.packages.BuildType.LABEL_LIST; 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.BuildConfiguration; import com.google.devtools.build.lib.cmdline.Label; import com.google.devtools.build.lib.packages.Attribute; -import com.google.devtools.build.lib.packages.AttributeMap; -import com.google.devtools.build.lib.packages.Rule; import com.google.devtools.build.lib.packages.RuleClass; import com.google.devtools.build.lib.packages.RuleClass.Builder; import com.google.devtools.build.lib.util.FileType; @@ -36,15 +33,16 @@ import com.google.devtools.build.lib.util.FileType; */ public final class BazelProtoLibraryRule implements RuleDefinition { - private static final Attribute.LateBoundLabel<BuildConfiguration> PROTO_COMPILER = - new Attribute.LateBoundLabel<BuildConfiguration>( - "@com_google_protobuf//:protoc", ProtoConfiguration.class) { - @Override - public Label resolve(Rule rule, AttributeMap attributes, BuildConfiguration configuration) { - Label label = configuration.getFragment(ProtoConfiguration.class).protoCompiler(); - return label != null ? label : getDefault(); - } - }; + private static final Label DEFAULT_PROTO_COMPILER = + Label.parseAbsoluteUnchecked("@com_google_protobuf//:protoc"); + private static final Attribute.LateBoundDefault<?, Label> PROTO_COMPILER = + Attribute.LateBoundDefault.fromTargetConfiguration( + ProtoConfiguration.class, + DEFAULT_PROTO_COMPILER, + (rule, attributes, protoConfig) -> + protoConfig.protoCompiler() != null + ? protoConfig.protoCompiler() + : DEFAULT_PROTO_COMPILER); @Override public RuleClass build(Builder builder, final RuleDefinitionEnvironment env) { diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/TransitiveTargetFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/TransitiveTargetFunction.java index 3f8a001961..093ec2c534 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/TransitiveTargetFunction.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/TransitiveTargetFunction.java @@ -197,9 +197,14 @@ public class TransitiveTargetFunction // Declared by late-bound attributes: for (Attribute attr : rule.getAttributes()) { - if (attr.isLateBound()) { - addFragmentsIfNew(builder, - attr.getLateBoundDefault().getRequiredConfigurationFragments()); + if (attr.isLateBound() + && attr.getLateBoundDefault().getFragmentClass() != null + && BuildConfiguration.Fragment.class.isAssignableFrom( + attr.getLateBoundDefault().getFragmentClass())) { + addFragmentIfNew( + builder, + (Class<? extends BuildConfiguration.Fragment>) + attr.getLateBoundDefault().getFragmentClass()); } } |