diff options
author | John Cater <jcater@google.com> | 2017-03-02 08:55:10 +0000 |
---|---|---|
committer | Yue Gan <yueg@google.com> | 2017-03-02 13:32:11 +0000 |
commit | 4f2b41d3f5fe936833380a0446adb671b8a50b1f (patch) | |
tree | 52f22bb8a592b779467b018bb4d2b5e6133f3f65 /src/main/java/com/google/devtools/build/lib/rules/platform | |
parent | 30a994102a3b7c856a313325051c10240f0ee3ef (diff) |
Add platform rule to define a platform as a collection of constraint values.
Part of ongoing work on #2219.
--
Change-Id: Ie4e842a5d8218e47f41a954c2b955ab24237aa65
Reviewed-on: https://cr.bazel.build/9116
PiperOrigin-RevId: 148976893
MOS_MIGRATED_REVID=148976893
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/rules/platform')
3 files changed, 226 insertions, 0 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/rules/platform/Platform.java b/src/main/java/com/google/devtools/build/lib/rules/platform/Platform.java new file mode 100644 index 0000000000..f652383757 --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/rules/platform/Platform.java @@ -0,0 +1,101 @@ +// Copyright 2017 The Bazel Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.devtools.build.lib.rules.platform; + +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Iterables; +import com.google.common.collect.Multimap; +import com.google.devtools.build.lib.analysis.ConfiguredTarget; +import com.google.devtools.build.lib.analysis.FileProvider; +import com.google.devtools.build.lib.analysis.FilesToRunProvider; +import com.google.devtools.build.lib.analysis.RuleConfiguredTarget.Mode; +import com.google.devtools.build.lib.analysis.RuleConfiguredTargetBuilder; +import com.google.devtools.build.lib.analysis.RuleContext; +import com.google.devtools.build.lib.analysis.RunfilesProvider; +import com.google.devtools.build.lib.rules.RuleConfiguredTargetFactory; + +/** Defines a platform for execution contexts. */ +public class Platform implements RuleConfiguredTargetFactory { + @Override + public ConfiguredTarget create(RuleContext ruleContext) + throws InterruptedException, RuleErrorException { + + Iterable<ConstraintValueProvider> constraintValues = + ruleContext.getPrerequisites( + PlatformRule.CONSTRAINT_VALUES_ATTR, Mode.DONT_CHECK, ConstraintValueProvider.class); + + // Verify the constraints - no two values for the same setting, and construct the map. + ImmutableMap<ConstraintSettingProvider, ConstraintValueProvider> constraints = + validateConstraints(ruleContext, constraintValues); + if (constraints == null) { + // An error occurred, return null. + return null; + } + + return new RuleConfiguredTargetBuilder(ruleContext) + .addProvider(RunfilesProvider.class, RunfilesProvider.EMPTY) + .addProvider(FileProvider.class, FileProvider.EMPTY) + .addProvider(FilesToRunProvider.class, FilesToRunProvider.EMPTY) + .addProvider(PlatformProvider.class, PlatformProvider.create(constraints)) + .build(); + } + + private ImmutableMap<ConstraintSettingProvider, ConstraintValueProvider> validateConstraints( + RuleContext ruleContext, Iterable<ConstraintValueProvider> constraintValues) { + Multimap<ConstraintSettingProvider, ConstraintValueProvider> constraints = + ArrayListMultimap.create(); + + for (ConstraintValueProvider constraintValue : constraintValues) { + constraints.put(constraintValue.constraint(), constraintValue); + } + + // Are there any settings with more than one value? + boolean foundError = false; + for (ConstraintSettingProvider constraintSetting : constraints.keySet()) { + if (constraints.get(constraintSetting).size() > 1) { + foundError = true; + // error + StringBuilder constraintValuesDescription = new StringBuilder(); + for (ConstraintValueProvider constraintValue : constraints.get(constraintSetting)) { + if (constraintValuesDescription.length() > 0) { + constraintValuesDescription.append(", "); + } + constraintValuesDescription.append(constraintValue.value()); + } + ruleContext.attributeError( + PlatformRule.CONSTRAINT_VALUES_ATTR, + String.format( + "Duplicate constraint_values for constraint_setting %s: %s", + constraintSetting.constraintSetting(), constraintValuesDescription.toString())); + } + } + + if (foundError) { + return null; + } + + // Convert to a flat map. + ImmutableMap.Builder<ConstraintSettingProvider, ConstraintValueProvider> builder = + new ImmutableMap.Builder<>(); + for (ConstraintSettingProvider constraintSetting : constraints.keySet()) { + ConstraintValueProvider constraintValue = + Iterables.getOnlyElement(constraints.get(constraintSetting)); + builder.put(constraintSetting, constraintValue); + } + + return builder.build(); + } +} diff --git a/src/main/java/com/google/devtools/build/lib/rules/platform/PlatformProvider.java b/src/main/java/com/google/devtools/build/lib/rules/platform/PlatformProvider.java new file mode 100644 index 0000000000..7a06c1f138 --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/rules/platform/PlatformProvider.java @@ -0,0 +1,32 @@ +// Copyright 2017 The Bazel Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.devtools.build.lib.rules.platform; + +import com.google.auto.value.AutoValue; +import com.google.common.collect.ImmutableMap; +import com.google.devtools.build.lib.analysis.TransitiveInfoProvider; +import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable; + +/** Provider for a platform, which is a group of constraints and values. */ +@AutoValue +@Immutable +public abstract class PlatformProvider implements TransitiveInfoProvider { + public abstract ImmutableMap<ConstraintSettingProvider, ConstraintValueProvider> constraints(); + + public static PlatformProvider create( + ImmutableMap<ConstraintSettingProvider, ConstraintValueProvider> constraints) { + return new AutoValue_PlatformProvider(constraints); + } +} diff --git a/src/main/java/com/google/devtools/build/lib/rules/platform/PlatformRule.java b/src/main/java/com/google/devtools/build/lib/rules/platform/PlatformRule.java new file mode 100644 index 0000000000..29537a4fb0 --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/rules/platform/PlatformRule.java @@ -0,0 +1,93 @@ +// Copyright 2017 The Bazel Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.devtools.build.lib.rules.platform; + +import static com.google.devtools.build.lib.packages.Attribute.attr; + +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.TransitiveInfoProvider; +import com.google.devtools.build.lib.packages.BuildType; +import com.google.devtools.build.lib.packages.RuleClass; +import com.google.devtools.build.lib.syntax.Type; +import com.google.devtools.build.lib.util.FileTypeSet; + +/** Rule definition for {@link Platform}. */ +public class PlatformRule implements RuleDefinition { + public static final String RULE_NAME = "platform"; + public static final String CONSTRAINT_VALUES_ATTR = "constraint_values"; + + @Override + public RuleClass build(RuleClass.Builder builder, RuleDefinitionEnvironment env) { + /* <!-- #BLAZE_RULE(platform).NAME --> + <!-- #END_BLAZE_RULE.NAME --> */ + return builder + .override( + attr("tags", Type.STRING_LIST) + // No need to show up in ":all", etc. target patterns. + .value(ImmutableList.of("manual")) + .nonconfigurable("low-level attribute, used in platform configuration")) + .add( + attr(CONSTRAINT_VALUES_ATTR, BuildType.LABEL_LIST) + .allowedFileTypes(FileTypeSet.NO_FILE) + .mandatoryNativeProviders( + ImmutableList.<Class<? extends TransitiveInfoProvider>>of( + ConstraintValueProvider.class))) + .removeAttribute("deps") + .removeAttribute("data") + .exemptFromConstraintChecking("this rule is part of constraint definition") + .build(); + } + + @Override + public Metadata getMetadata() { + return Metadata.builder() + .name(RULE_NAME) + .ancestors(BaseRuleClasses.RuleBase.class) + .factoryClass(Platform.class) + .build(); + } +} +/*<!-- #BLAZE_RULE (NAME = platform, TYPE = OTHER, FAMILY = Platform)[GENERIC_RULE] --> + +<p>This rule defines a platform, as a collection of constraint_values. + +<h4 id="platform_examples">Examples</h4> +<p> + This defines two possible platforms, each targeting a different CPU type. +</p> +<pre class="code"> +constraint_setting(name="cpu") +constraint_value( + name="arm64", + constraint=":cpu") +constraint_value( + name="k8", + constraint=":cpu") +platform( + name="mobile_device", + constraints = [ + ":arm64", + ]) +platform( + name="devel", + constraints = [ + ":k8", + ]) +</pre> + +<!-- #END_BLAZE_RULE -->*/ |