| // 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.common.collect.ImmutableMap; |
| 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.transitions.NoConfigTransition; |
| import com.google.devtools.build.lib.analysis.platform.ConstraintValueInfo; |
| import com.google.devtools.build.lib.analysis.platform.PlatformInfo; |
| import com.google.devtools.build.lib.packages.BuildType; |
| import com.google.devtools.build.lib.packages.RuleClass; |
| import com.google.devtools.build.lib.packages.RuleClass.ToolchainResolutionMode; |
| import com.google.devtools.build.lib.packages.Type; |
| import com.google.devtools.build.lib.packages.Types; |
| 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"; |
| public static final String PARENTS_PLATFORM_ATTR = "parents"; |
| public static final String REMOTE_EXECUTION_PROPS_ATTR = "remote_execution_properties"; |
| public static final String EXEC_PROPS_ATTR = "exec_properties"; |
| public static final String FLAGS_ATTR = "flags"; |
| |
| @Override |
| public RuleClass build(RuleClass.Builder builder, RuleDefinitionEnvironment env) { |
| /* <!-- #BLAZE_RULE(platform).NAME --> |
| <!-- #END_BLAZE_RULE.NAME --> */ |
| return builder |
| .advertiseStarlarkProvider(PlatformInfo.PROVIDER.id()) |
| .cfg(NoConfigTransition.createFactory()) |
| .exemptFromConstraintChecking("this rule helps *define* a constraint") |
| .useToolchainResolution(ToolchainResolutionMode.DISABLED) |
| .removeAttribute(":action_listener") |
| .removeAttribute(RuleClass.APPLICABLE_METADATA_ATTR) |
| .override( |
| attr("tags", Types.STRING_LIST) |
| // No need to show up in ":all", etc. target patterns. |
| .value(ImmutableList.of("manual")) |
| .nonconfigurable("low-level attribute, used in platform configuration")) |
| /* <!-- #BLAZE_RULE(platform).ATTRIBUTE(constraint_values) --> |
| The combination of constraint choices that this platform comprises. In order for a platform |
| to apply to a given environment, the environment must have at least the values in this list. |
| |
| <p>Each <code>constraint_value</code> in this list must be for a different |
| <code>constraint_setting</code>. For example, you cannot define a platform that requires the |
| cpu architecture to be both <code>@platforms//cpu:x86_64</code> and |
| <code>@platforms//cpu:arm</code>. |
| <!-- #END_BLAZE_RULE.ATTRIBUTE --> */ |
| .add( |
| attr(CONSTRAINT_VALUES_ATTR, BuildType.LABEL_LIST) |
| .allowedFileTypes(FileTypeSet.NO_FILE) |
| .mandatoryProviders(ConstraintValueInfo.PROVIDER.id()) |
| .nonconfigurable("Part of the configuration")) |
| |
| /* <!-- #BLAZE_RULE(platform).ATTRIBUTE(parents) --> |
| The label of a <code>platform</code> target that this platform should inherit from. Although |
| the attribute takes a list, there should be no more than one platform present. Any |
| constraint_settings not set directly on this platform will be found in the parent platform. |
| See the section on <a href="#platform_inheritance">Platform Inheritance</a> for details. |
| <!-- #END_BLAZE_RULE.ATTRIBUTE --> */ |
| .add( |
| attr(PARENTS_PLATFORM_ATTR, BuildType.LABEL_LIST) |
| .allowedFileTypes(FileTypeSet.NO_FILE) |
| .mandatoryProviders(PlatformInfo.PROVIDER.id()) |
| .nonconfigurable("Part of the configuration")) |
| |
| /* <!-- #BLAZE_RULE(platform).ATTRIBUTE(remote_execution_properties) --> |
| DEPRECATED. Please use exec_properties attribute instead. |
| |
| A string used to configure a remote execution platform. Actual builds make no attempt to |
| interpret this, it is treated as opaque data that can be used by a specific SpawnRunner. |
| This can include data from the parent platform's "remote_execution_properties" attribute, |
| by using the macro "{PARENT_REMOTE_EXECUTION_PROPERTIES}". See the section on |
| <a href="#platform_inheritance">Platform Inheritance</a> for details. |
| <!-- #END_BLAZE_RULE.ATTRIBUTE --> */ |
| .add( |
| attr(REMOTE_EXECUTION_PROPS_ATTR, Type.STRING) |
| .nonconfigurable("Part of the configuration")) |
| |
| /* <!-- #BLAZE_RULE(platform).ATTRIBUTE(exec_properties) --> |
| A map of strings that affect the way actions are executed remotely. Bazel makes no attempt |
| to interpret this, it is treated as opaque data that's forwarded via the Platform field of |
| the <a href="https://github.com/bazelbuild/remote-apis">remote execution protocol</a>. |
| |
| This includes any data from the parent platform's <code>exec_properties</code> attributes. |
| If the child and parent platform define the same keys, the child's values are kept. Any |
| keys associated with a value that is an empty string are removed from the dictionary. |
| |
| This attribute is a full replacement for the deprecated |
| <code>remote_execution_properties</code>. |
| <!-- #END_BLAZE_RULE.ATTRIBUTE --> */ |
| .add( |
| attr(EXEC_PROPS_ATTR, Types.STRING_DICT) |
| .value(ImmutableMap.of()) |
| .nonconfigurable("Part of the configuration")) |
| |
| /* <!-- #BLAZE_RULE(platform).ATTRIBUTE(flags) --> |
| A list of flags that will be enabled when this platform is used as the target platform in |
| a configuration. Only flags that can be set in transitions are allowed to be used. |
| <!-- #END_BLAZE_RULE.ATTRIBUTE --> */ |
| .add( |
| attr(FLAGS_ATTR, Types.STRING_LIST) |
| .value(ImmutableList.of()) |
| .nonconfigurable("Part of the configuration")) |
| .build(); |
| } |
| |
| @Override |
| public Metadata getMetadata() { |
| return Metadata.builder() |
| .name(RULE_NAME) |
| .ancestors(BaseRuleClasses.NativeBuildRule.class) |
| .factoryClass(Platform.class) |
| .build(); |
| } |
| } |
| /*<!-- #FAMILY_SUMMARY --> |
| |
| <p> |
| This set of rules exists to allow you to model specific hardware platforms you are |
| building for and specify the specific tools you may need to compile code for those platforms. |
| The user should be familiar with the concepts explained <a href="/extending/platforms">here</a>. |
| </p> |
| |
| <!-- #END_FAMILY_SUMMARY -->*/ |
| |
| /*<!-- #BLAZE_RULE (NAME = platform, FAMILY = Platforms and Toolchains)[GENERIC_RULE] --> |
| |
| <p>This rule defines a new platform -- a named collection of constraint choices |
| (such as cpu architecture or compiler version) describing an environment in |
| which part of the build may run. |
| |
| For more details, see the <a href="/extending/platforms">Platforms</a> page. |
| |
| |
| <h4 id="platform_examples">Example</h4> |
| <p> |
| This defines a platform that describes any environment running Linux on ARM. |
| </p> |
| <pre class="code"> |
| platform( |
| name = "linux_arm", |
| constraint_values = [ |
| "@platforms//os:linux", |
| "@platforms//cpu:arm", |
| ], |
| ) |
| </pre> |
| |
| <h3 id="platform_inheritance">Platform Inheritance</h3> |
| <p> |
| Platforms may use the <code>parents</code> attribute to specify another platform that they will |
| inherit constraint values from. Although the <code>parents</code> attribute takes a list, no |
| more than a single value is currently supported, and specifying multiple parents is an error. |
| </p> |
| |
| <p> |
| When checking for the value of a constraint setting in a platform, first the values directly set |
| (via the <code>constraint_values</code> attribute) are checked, and then the constraint values on |
| the parent. This continues recursively up the chain of parent platforms. In this manner, any |
| values set directly on a platform will override the values set on the parent. |
| </p> |
| |
| <p> |
| Platforms inherit the <code>exec_properties</code> attribute from the parent platform. |
| The dictionary entries in <code>exec_properties</code> of the parent and child platforms |
| will be combined. |
| If the same key appears in both the parent's and the child's <code>exec_properties</code>, |
| the child's value will be used. If the child platform specifies an empty string as a value, the |
| corresponding property will be unset. |
| </p> |
| |
| <p> |
| Platforms can also inherit the (deprecated) <code>remote_execution_properties</code> attribute |
| from the parent platform. Note: new code should use <code>exec_properties</code> instead. The |
| logic described below is maintained to be compatible with legacy behavior but will be removed |
| in the future. |
| |
| The logic for setting the <code>remote_execution_platform</code> is as follows when there |
| is a parent platform: |
| |
| <ol> |
| <li> |
| If <code>remote_execution_property</code> is not set on the child platform, the parent's |
| <code>remote_execution_properties</code> will be used. |
| </li> |
| <li> |
| If <code>remote_execution_property</code> is set on the child platform, and contains the |
| literal string </code>{PARENT_REMOTE_EXECUTION_PROPERTIES}</code>, that macro will be |
| replaced with the contents of the parent's <code>remote_execution_property</code> attribute. |
| </li> |
| <li> |
| If <code>remote_execution_property</code> is set on the child platform, and does not contain |
| the macro, the child's <code>remote_execution_property</code> will be used unchanged. |
| </li> |
| </ol> |
| </p> |
| |
| <p> |
| <em>Since <code>remote_execution_properties</code> is deprecated and will be phased out, mixing |
| <code>remote_execution_properties</code> and <code>exec_properties</code> in the same |
| inheritance chain is not allowed.</em> |
| Prefer to use <code>exec_properties</code> over the deprecated |
| <code>remote_execution_properties</code>. |
| </p> |
| |
| <h4 id="platform_inheritance_examples">Example: Constraint Values</h4> |
| <pre class="code"> |
| platform( |
| name = "parent", |
| constraint_values = [ |
| "@platforms//os:linux", |
| "@platforms//cpu:arm", |
| ], |
| ) |
| platform( |
| name = "child_a", |
| parents = [":parent"], |
| constraint_values = [ |
| "@platforms//cpu:x86_64", |
| ], |
| ) |
| platform( |
| name = "child_b", |
| parents = [":parent"], |
| ) |
| </pre> |
| |
| <p> |
| In this example, the child platforms have the following properties: |
| |
| <ul> |
| <li> |
| <code>child_a</code> has the constraint values <code>@platforms//os:linux</code> (inherited |
| from the parent) and <code>@platforms//cpu:x86_64</code> (set directly on the platform). |
| </li> |
| <li> |
| <code>child_b</code> inherits all constraint values from the parent, and doesn't set any of |
| its own. |
| </li> |
| </ul> |
| </p> |
| |
| <h4 id="platform_inheritance_exec_examples">Example: Execution properties</h4> |
| <pre class="code"> |
| platform( |
| name = "parent", |
| exec_properties = { |
| "k1": "v1", |
| "k2": "v2", |
| }, |
| ) |
| platform( |
| name = "child_a", |
| parents = [":parent"], |
| ) |
| platform( |
| name = "child_b", |
| parents = [":parent"], |
| exec_properties = { |
| "k1": "child" |
| } |
| ) |
| platform( |
| name = "child_c", |
| parents = [":parent"], |
| exec_properties = { |
| "k1": "" |
| } |
| ) |
| platform( |
| name = "child_d", |
| parents = [":parent"], |
| exec_properties = { |
| "k3": "v3" |
| } |
| ) |
| </pre> |
| |
| <p> |
| In this example, the child platforms have the following properties: |
| |
| <ul> |
| <li> |
| <code>child_a</code> inherits the "exec_properties" of the parent and does not set its own. |
| </li> |
| <li> |
| <code>child_b</code> inherits the parent's <code>exec_properties</code> and overrides the |
| value of <code>k1</code>. Its <code>exec_properties</code> will be: |
| <code>{ "k1": "child", "k2": "v2" }</code>. |
| </li> |
| <li> |
| <code>child_c</code> inherits the parent's <code>exec_properties</code> and unsets |
| <code>k1</code>. Its <code>exec_properties</code> will be: |
| <code>{ "k2": "v2" }</code>. |
| </li> |
| <li> |
| <code>child_d</code> inherits the parent's <code>exec_properties</code> and adds a new |
| property. Its <code>exec_properties</code> will be: |
| <code>{ "k1": "v1", "k2": "v2", "k3": "v3" }</code>. |
| </li> |
| </ul> |
| </p> |
| |
| <!-- #END_BLAZE_RULE -->*/ |