// Copyright 2014 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.config; import static com.google.devtools.build.lib.packages.Attribute.attr; import static com.google.devtools.build.lib.packages.BuildType.LABEL_KEYED_STRING_DICT; import static com.google.devtools.build.lib.syntax.Type.STRING; import static com.google.devtools.build.lib.syntax.Type.STRING_DICT; import static com.google.devtools.build.lib.syntax.Type.STRING_LIST; import com.google.common.base.Function; import com.google.common.collect.ImmutableList; import com.google.devtools.build.lib.analysis.BaseRuleClasses; 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.packages.NonconfigurableAttributeMapper; import com.google.devtools.build.lib.packages.Rule; import com.google.devtools.build.lib.packages.RuleClass; import com.google.devtools.build.lib.syntax.Type; import java.util.Set; /** * Definitions for rule classes that specify or manipulate configuration settings. * *
These are not "traditional" rule classes in that they can't be requested as top-level * targets and don't translate input artifacts into output artifacts. Instead, they affect * how *other* rules work. See individual class comments for details. */ public class ConfigRuleClasses { private static final String NONCONFIGURABLE_ATTRIBUTE_REASON = "part of a rule class that *triggers* configurable behavior"; /** * Common settings for all configurability rules. */ public static final class ConfigBaseRule implements RuleDefinition { @Override public RuleClass build(RuleClass.Builder builder, RuleDefinitionEnvironment env) { return builder .override(attr("tags", Type.STRING_LIST) // No need to show up in ":all", etc. target patterns. .value(ImmutableList.of("manual")) .nonconfigurable(NONCONFIGURABLE_ATTRIBUTE_REASON)) .exemptFromConstraintChecking( "these rules don't include content that gets built into their dependers") .build(); } @Override public Metadata getMetadata() { return RuleDefinition.Metadata.builder() .name("$config_base_rule") .type(RuleClass.Builder.RuleClassType.ABSTRACT) .ancestors(BaseRuleClasses.BaseRule.class) .build(); } } /** * A named "partial configuration setting" that specifies a set of command-line * "flag=value" bindings. * *
For example: *
* config_setting( * name = 'foo', * values = { * 'flag1': 'aValue' * 'flag2': 'bValue' * }) ** *
declares a setting that binds command-line flag
flag1to value *
aValueand
flag2to
bValue. * *
This is used by configurable attributes to determine which branch to * follow based on which
config_settinginstance matches all its * flag values in the configurable attribute owner's configuration. * *
This rule isn't accessed through the standard {@link RuleContext#getPrerequisites}
* interface. This is because Bazel constructs a rule's configured attribute map *before*
* its {@link RuleContext} is created (in fact, the map is an input to the context's
* constructor). And the config_settings referenced by the rule's configurable attributes are
* themselves inputs to that map. So Bazel has special logic to read and properly apply
* config_setting instances. See {@link ConfiguredTargetFunction#getConfigConditions} for details.
*/
public static final class ConfigSettingRule implements RuleDefinition {
/**
* The name of this rule.
*/
public static final String RULE_NAME = "config_setting";
/**
* The name of the attribute that declares flag bindings.
*/
public static final String SETTINGS_ATTRIBUTE = "values";
/** The name of the attribute that declares user-defined flag bindings. */
public static final String FLAG_SETTINGS_ATTRIBUTE = "flag_values";
private static final Function This rule inherits the configuration of the configured target that
references it in a For convenience's sake, configuration values are specified as Blaze flags (without
the preceding If a flag is not explicitly set at the command line, its default value is used.
If a key appears multiple times in the dictionary, only the last instance is used.
If a key references a flag that can be set multiple times on the command line (e.g.
This attribute cannot be empty.
Matches an expected configuration state (expressed as Blaze flags) for the purpose of triggering
configurable attributes. See select for how to consume this
rule and
Configurable attributes for an overview of the general feature.
The following matches any Blaze invocation that specifies The following matches any Blaze invocation that builds for ARM and applies a custom define
(e.g. See select for policies on what happens depending on how
many rules match an invocation.
For flags that support shorthand forms (e.g. The currently endorsed method for creating custom conditions that can't be expressed through
dedicated build flags is through the --define flag. Use this flag with caution: it's not ideal
and only endorsed for lack of a currently better workaround. See the
Configurable attributes section for more discussion.
Try to consolidate select
statement. It is considered to
"match" a Blaze invocation if, for every entry in the dictionary, its
configuration matches the entry's expected value. For example
values = {"compilation_mode": "opt"}
matches the invocations
blaze build --compilation_mode=opt ...
and
blaze build -c opt ...
on target-configured rules.
"--"
). But keep in mind that the two are not the same. This
is because targets can be built in multiple configurations within the same
build. For example, a host configuration's "cpu" matches the value of
--host_cpu
, not --cpu
. So different instances of the
same config_setting
may match the same invocation differently
depending on the configuration of the rule using them.
blaze build --copt=foo --copt=bar --copt=baz ...
), a match occurs if
any of those settings match.
Examples
--compilation_mode=opt
or -c opt
(either explicitly at the command line or implicitly from .blazerc
files, etc.), when applied to a target configuration rule:
config_setting(
name = "simple",
values = {"compilation_mode": "opt"}
)
blaze build --cpu=armeabi --define FOO=bar ...
), when applied to a target
configuration rule:
config_setting(
name = "two_conditions",
values = {
"cpu": "armeabi",
"define": "FOO=bar"
}
)
Notes
--compilation_mode
vs.
-c
), values
definitions must use the full form. These automatically
match invocations using either form.
config_setting
definitions as much as possible. In other words,
define //common/conditions:foo
in one common package instead of repeating separate
instances in //project1:foo
, //project2:foo
, etc. that all mean the
same thing.