// 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.packages.BuildType.LABEL_LIST;
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.collect.ImmutableList;
import com.google.devtools.build.lib.analysis.BaseRuleClasses;
import com.google.devtools.build.lib.analysis.PlatformConfiguration;
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.cmdline.Label;
import com.google.devtools.build.lib.packages.Attribute.LabelListLateBoundDefault;
import com.google.devtools.build.lib.packages.AttributeMap;
import com.google.devtools.build.lib.packages.NonconfigurableAttributeMapper;
import com.google.devtools.build.lib.packages.RuleClass;
import com.google.devtools.build.lib.syntax.Type;
import java.util.List;

/**
 * Definitions for rule classes that specify or manipulate configuration settings.
 *
 * <p>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.
   *
   * <p>For example:
   * <pre>
   *   config_setting(
   *       name = 'foo',
   *       values = {
   *           'flag1': 'aValue'
   *           'flag2': 'bValue'
   *       })
   * </pre>
   *
   * <p>declares a setting that binds command-line flag <pre>flag1</pre> to value
   * <pre>aValue</pre> and <pre>flag2</pre> to <pre>bValue</pre>.
   *
   * <p>This is used by configurable attributes to determine which branch to
   * follow based on which <pre>config_setting</pre> instance matches all its
   * flag values in the configurable attribute owner's configuration.
   *
   * <p>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 "--define foo=bar" flag bindings.*/
    public static final String DEFINE_SETTINGS_ATTRIBUTE = "define_values";
    /** The name of the attribute that declares user-defined flag bindings. */
    public static final String FLAG_SETTINGS_ATTRIBUTE = "flag_values";
    /** The name of the attribute that declares constraint_values. */
    public static final String CONSTRAINT_VALUES_ATTRIBUTE = "constraint_values";
    /** The name of the late bound attribute that declares the target platforms list. */
    public static final String TARGET_PLATFORMS_ATTRIBUTE = ":target_platforms";

    /** Implementation for the :target_platform attribute. */
    public static final LabelListLateBoundDefault<?> TARGET_PLATFORMS =
        LabelListLateBoundDefault.fromTargetConfiguration(
            PlatformConfiguration.class,
            (rule, attributes, platformConfig) ->
                ConfigSettingRule.getTargetPlatformsIfRelevant(attributes, platformConfig));

    private static ImmutableList<Label> getTargetPlatformsIfRelevant(
        AttributeMap attributes, PlatformConfiguration platformConfig) {
      List<Label> constraintValues = attributes.get(CONSTRAINT_VALUES_ATTRIBUTE, LABEL_LIST);
      if (constraintValues == null || constraintValues.isEmpty()) {
        return ImmutableList.of();
      } else {
        return platformConfig.getTargetPlatforms();
      }
    }

    @Override
    public RuleClass build(RuleClass.Builder builder, RuleDefinitionEnvironment env) {
      return builder
          /* <!-- #BLAZE_RULE(config_setting).ATTRIBUTE(values) -->
          The set of configuration values that match this rule (expressed as Blaze flags)

          <i>(Dictionary mapping flags to expected values, both expressed as strings;
             mandatory)</i>

          <p>This rule inherits the configuration of the configured target that
            references it in a <code>select</code> 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
            <code>values = {"compilation_mode": "opt"}</code> matches the invocations
            <code>blaze build --compilation_mode=opt ...</code> and
            <code>blaze build -c opt ...</code> on target-configured rules.
          </p>

          <p>For convenience's sake, configuration values are specified as Blaze flags (without
            the preceding <code>"--"</code>). 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
            <code>--host_cpu</code>, not <code>--cpu</code>. So different instances of the
            same <code>config_setting</code> may match the same invocation differently
            depending on the configuration of the rule using them.
          </p>

          <p>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.
             <code>blaze build --copt=foo --copt=bar --copt=baz ...</code>), a match occurs if
             <i>any</i> of those settings match.
          <p>

          <p>This and <a href="${link config_setting.define_values}"><code>define_values</code></a>
             cannot both be empty.
          </p>
          <!-- #END_BLAZE_RULE.ATTRIBUTE --> */
          .add(
              attr(SETTINGS_ATTRIBUTE, STRING_DICT)
                  .nonconfigurable(NONCONFIGURABLE_ATTRIBUTE_REASON))
          /* <!-- #BLAZE_RULE(config_setting).ATTRIBUTE(define_values) -->
          The same as <a href="${link config_setting.values}"><code>values</code></a> but
          specifically for the <code>--define</code> flag.

          <p><code>--define</code> is special for two reasons:

          <ol>
            <li>It's the primary interface Blaze has today for declaring user-definable settings.
            </li>
            <li>Its syntax (<code>--define KEY=VAL</code>) means <code>KEY=VAL</code> is
            a <i>value</i> from a Blaze flag perspective.</li>
          </ol>

          <p>That means:

          <pre class="code">
            config_setting(
                name = "a_and_b",
                values = {
                    "define": "a=1",
                    "define": "b=2",
                })
          </pre>

          <p>doesn't work because the same key (<code>define</code>) appears twice in the
          dictionary. This attribute solves that problem:

          <pre class="code">
            config_setting(
                name = "a_and_b",
                define_values = {
                    "a": "1",
                    "b": "2",
                })
          </pre>

          <p>corrrectly matches <code>blaze build //foo --define a=1 --define b=2</code>.

          <p><code>--define</code> can still appear in
          <a href="${link config_setting.values}"><code>values</code></a> with normal flag syntax,
          and can be mixed freely with this attribute as long as dictionary keys remain distinct.
          <!-- #END_BLAZE_RULE.ATTRIBUTE --> */
          .add(
              attr(DEFINE_SETTINGS_ATTRIBUTE, STRING_DICT)
                  .nonconfigurable(NONCONFIGURABLE_ATTRIBUTE_REASON))
          .add(
              attr(FLAG_SETTINGS_ATTRIBUTE, LABEL_KEYED_STRING_DICT)
                  .undocumented("the feature flag feature has not yet been launched")
                  .allowedFileTypes()
                  .mandatoryProviders(ImmutableList.of(ConfigFeatureFlagProvider.id()))
                  .nonconfigurable(NONCONFIGURABLE_ATTRIBUTE_REASON))
          /* <!-- #BLAZE_RULE(config_setting).ATTRIBUTE(constraint_values) -->
          The set of <code>constraint_values</code> that match this rule.

          <p>A <a href="platform.html#constraint_value">constraint_value</a> is composed of a name
          and a corresponding <a href="platform.html#constraint_setting">constraint_setting</a>
          which classifies the value. A <a href=""platform.html#platform>platform</a> consists of a
          collection of <code>constraint_value</code> labels which describes target itself and/or
          how its environment.
          </p>

          <pre class="code">
            constraint_setting(name = "rock_type")
            constraint_value(name = metamorphic, constraint_setting = "rock_type")
            platform(
              name = "my_platform_rocks",
              constraint_values = [":metamorphic"]
            )
          </pre>

          <p>As mentioned above, this rule inherits the configuration of the configured target that
            references it in a <code>select</code> statement. This <code>constraint_values</code>
            attribute is considered to "match" a Blaze invocation if it includes each
            <code>constraint_value</code> specified in the configuration's target platform which is
            set with the command line flag <code>--experimental_platforms</code>. If it contains
            extra <code>constraint_values</code> not included in the target platform, it is still
            considered a match. In this example, both <code>slate</code> and
            <code>marble</code> would be considered matches for a blaze invocation which
            uses <code>--experimental_platforms=my_platform_rocks</code>. Multiple matches like this
            may lead to ambiguous select resolves and are not allowed.
          </p>
          <pre class = "code">
            constraint_setting(name = "color")
            constraint_value(name = "white", constraint_setting = "color")

            config_setting(
              name = "slate",
              constraint_values = [":metamorphic"]
            )

            config_setting(
              name = "marble",
              constraint_values = [
                ":metamorphic",
                ":white"
              ]
            )
          </pre>
          <!-- #END_BLAZE_RULE.ATTRIBUTE --> */
          .add(
              attr(CONSTRAINT_VALUES_ATTRIBUTE, LABEL_LIST)
                  .nonconfigurable(NONCONFIGURABLE_ATTRIBUTE_REASON)
                  .allowedFileTypes())
          .add(
              attr(TARGET_PLATFORMS_ATTRIBUTE, LABEL_LIST)
                  .value(TARGET_PLATFORMS)
                  .nonconfigurable(NONCONFIGURABLE_ATTRIBUTE_REASON))
          .setIsConfigMatcherForConfigSettingOnly()
          .setOptionReferenceFunctionForConfigSettingOnly(
              rule ->
                  NonconfigurableAttributeMapper.of(rule)
                      .get(SETTINGS_ATTRIBUTE, Type.STRING_DICT)
                      .keySet())
          .build();
    }

    @Override
    public Metadata getMetadata() {
      return RuleDefinition.Metadata.builder()
          .name(RULE_NAME)
          .type(RuleClass.Builder.RuleClassType.NORMAL)
          .ancestors(ConfigBaseRule.class)
          .factoryClass(ConfigSetting.class)
          .build();
    }
  }
/*<!-- #BLAZE_RULE (NAME = config_setting, TYPE = OTHER, FAMILY = General)[GENERIC_RULE] -->

<p>
  Matches an expected configuration state (expressed as Blaze flags) for the purpose of triggering
  configurable attributes. See <a href="${link select}">select</a> for how to consume this
  rule and <a href="${link common-definitions#configurable-attributes}">
  Configurable attributes</a> for an overview of the general feature.

<h4 id="config_setting_examples">Examples</h4>

<p>The following matches any Blaze invocation that specifies <code>--compilation_mode=opt</code>
   or <code>-c opt</code> (either explicitly at the command line or implicitly from .blazerc
   files, etc.), when applied to a target configuration rule:
</p>

<pre class="code">
config_setting(
    name = "simple",
    values = {"compilation_mode": "opt"}
)
</pre>

<p>The following matches any Blaze invocation that builds for ARM and applies a custom define
   (e.g. <code>blaze build --cpu=armeabi --define FOO=bar ...</code>), when applied to a target
   configuration rule:
</p>

<pre class="code">
config_setting(
    name = "two_conditions",
    values = {
        "cpu": "armeabi",
        "define": "FOO=bar"
    }
)
</pre>

<p>The following config_setting matches any Blaze invocation that builds a platform which contains
  exactly the same or a subset of its constraint_values (like the example below).
</p>

<pre class=""code">
config_setting(
    name = "marble",
    constraint_values = [
        "white",
        "metamorphic",
    ]
)

platform(
    name = "marble_platform",
    constraint_values = [
        "white",
        "metamorphic"
    ]
)
</pre>

<h4 id="config_setting_notes">Notes</h4>

<p>See <a href="${link select}">select</a> for policies on what happens depending on how
   many rules match an invocation.
</p>

<p>For flags that support shorthand forms (e.g. <code>--compilation_mode</code> vs.
  <code>-c</code>), <code>values</code> definitions must use the full form. These automatically
  match invocations using either form.
</p>

<p>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
  <a href="${link common-definitions#configurable-attributes}">
  Configurable attributes</a> section for more discussion.
</p>

<p>Try to consolidate <code>config_setting</code> definitions as much as possible. In other words,
  define <code>//common/conditions:foo</code> in one common package instead of repeating separate
  instances in <code>//project1:foo</code>, <code>//project2:foo</code>, etc. that all mean the
  same thing.
</p>

<p><a href="general.html#config_setting.values"><code>values</code></a>,
   <a href="general.html#config_setting.define_values"><code>define_values</code></a>, and
   <a href=general.html#config_setting.constraint_values"><code>constraint_values</code></a>
   can be used in any combination in the same config_setting but at least one must be set for any
   given config_setting.
</p>

<!-- #END_BLAZE_RULE -->*/

  /** Rule definition for Android's config_feature_flag rule. */
  public static final class ConfigFeatureFlagRule implements RuleDefinition {

    @Override
    public RuleClass build(RuleClass.Builder builder, RuleDefinitionEnvironment env) {
      return builder
          .setUndocumented(/* the feature flag feature has not yet been launched */)
          .requiresConfigurationFragments(ConfigFeatureFlagConfiguration.class)
          .add(
              attr("allowed_values", STRING_LIST)
                  .mandatory()
                  .nonEmpty()
                  .orderIndependent()
                  .nonconfigurable(NONCONFIGURABLE_ATTRIBUTE_REASON))
          .add(
              attr("default_value", STRING)
                  .nonconfigurable(NONCONFIGURABLE_ATTRIBUTE_REASON))
          .add(ConfigFeatureFlag.getWhitelistAttribute(env))
          .build();
    }

    @Override
    public RuleDefinition.Metadata getMetadata() {
      return RuleDefinition.Metadata.builder()
          .name("config_feature_flag")
          .ancestors(ConfigBaseRule.class)
          .factoryClass(ConfigFeatureFlag.class)
          .build();
    }
  }
}
