// 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.analysis.config;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedMap;
import com.google.common.collect.Interner;
import com.google.devtools.build.lib.actions.ActionEnvironment;
import com.google.devtools.build.lib.actions.ArtifactRoot;
import com.google.devtools.build.lib.actions.BuildConfigurationEvent;
import com.google.devtools.build.lib.actions.CommandLineLimits;
import com.google.devtools.build.lib.analysis.BlazeDirectories;
import com.google.devtools.build.lib.analysis.PlatformOptions;
import com.google.devtools.build.lib.buildeventstream.BuildEvent;
import com.google.devtools.build.lib.buildeventstream.BuildEventIdUtil;
import com.google.devtools.build.lib.buildeventstream.BuildEventStreamProtos;
import com.google.devtools.build.lib.buildeventstream.BuildEventStreamProtos.BuildEventId;
import com.google.devtools.build.lib.buildeventstream.NullConfiguration;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.cmdline.RepositoryName;
import com.google.devtools.build.lib.concurrent.BlazeInterners;
import com.google.devtools.build.lib.events.EventHandler;
import com.google.devtools.build.lib.packages.BuiltinRestriction;
import com.google.devtools.build.lib.skyframe.config.BuildConfigurationKey;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
import com.google.devtools.build.lib.starlarkbuildapi.BuildConfigurationApi;
import com.google.devtools.build.lib.util.OS;
import com.google.devtools.build.lib.util.RegexFilter;
import com.google.devtools.build.lib.vfs.PathFragment;
import com.google.devtools.build.skyframe.SkyValue;
import com.google.devtools.common.options.TriState;
import java.io.PrintStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import javax.annotation.Nullable;
import net.starlark.java.annot.StarlarkAnnotations;
import net.starlark.java.annot.StarlarkBuiltin;
import net.starlark.java.eval.EvalException;
import net.starlark.java.eval.StarlarkThread;

/**
 * Represents a collection of context information which may affect a build (for example: the target
 * platform for compilation, or whether or not debug tables are required). In fact, all
 * "environmental" information (e.g. from the tool's command-line, as opposed to the BUILD file)
 * that can affect the output of any build tool should be explicitly represented in the {@code
 * BuildConfigurationValue} instance.
 *
 * <p>A single build may require building tools to run on a variety of platforms: when compiling a
 * server application for production, we must build the build tools (like compilers) to run on the
 * execution platform, but cross-compile the application for the production environment.
 *
 * <p>There is always at least one {@code BuildConfigurationValue} instance in any build: the one
 * representing the target platform. Additional instances may be created, in a cross-compilation
 * build, for example.
 *
 * <p>Instances of {@code BuildConfigurationValue} are canonical:
 *
 * <pre>{@code c1.equals(c2) <=> c1==c2.}</pre>
 */
@AutoCodec
public class BuildConfigurationValue
    implements BuildConfigurationApi, SkyValue, BuildConfigurationInfo {

  private static final Interner<ImmutableSortedMap<Class<? extends Fragment>, Fragment>>
      fragmentsInterner = BlazeInterners.newWeakInterner();

  private static final ImmutableSet<BuiltinRestriction.AllowlistEntry> ANDROID_ALLOWLIST =
      ImmutableSet.of(
          BuiltinRestriction.allowlistEntry("", "third_party/bazel_rules/rules_android"),
          BuiltinRestriction.allowlistEntry("build_bazel_rules_android", ""),
          BuiltinRestriction.allowlistEntry("rules_android", ""),
          BuiltinRestriction.allowlistEntry("", "tools/build_defs/android"));

  /** Global state necessary to build a BuildConfiguration. */
  public interface GlobalStateProvider {
    /** Computes the default shell environment for actions from the command line options. */
    ActionEnvironment getActionEnvironment(BuildOptions options);

    FragmentRegistry getFragmentRegistry();

    ImmutableSet<String> getReservedActionMnemonics();
  }

  private final OutputDirectories outputDirectories;

  private final ImmutableSortedMap<Class<? extends Fragment>, Fragment> fragments;

  private final ImmutableMap<String, Class<? extends Fragment>> starlarkVisibleFragments;
  private final String workspaceName;
  private final ImmutableSet<String> reservedActionMnemonics;
  private final CommandLineLimits commandLineLimits;

  /**
   * The global "make variables" such as "$(TARGET_CPU)"; these get applied to all rules analyzed in
   * this configuration.
   */
  private final ImmutableMap<String, String> globalMakeEnv;

  private final ActionEnvironment actionEnv;
  private final ActionEnvironment testEnv;

  private final BuildOptions buildOptions;
  private final CoreOptions options;

  /**
   * If non-empty, this is appended to output directories as ST-[transitionDirectoryNameFragment].
   * The value is a hash of BuildOptions that have been affected by a Starlark transition.
   *
   * <p>See b/203470434 or #14023 for more information and planned behavior changes.
   */
  private final String mnemonic;

  private final ImmutableMap<String, String> commandLineBuildVariables;

  /** Data for introspecting the options used by this configuration. */
  private final BuildOptionDetails buildOptionDetails;

  private final boolean siblingRepositoryLayout;

  private final FeatureSet defaultFeatures;

  @Nullable // lazily initialized
  private transient volatile BuildConfigurationEvent buildEvent;

  /**
   * Validates the options for this BuildConfigurationValue. Issues warnings for the use of
   * deprecated options, and warnings or errors for any option settings that conflict.
   */
  public void reportInvalidOptions(EventHandler reporter) {
    for (Fragment fragment : fragments.values()) {
      fragment.reportInvalidOptions(reporter, this.buildOptions);
    }
  }

  /**
   * Compute the test environment, which, at configuration level, is a pair consisting of the
   * statically set environment variables with their values and the set of environment variables to
   * be inherited from the client environment.
   */
  private ActionEnvironment setupTestEnvironment() {
    // We make a copy first to remove duplicate entries; last one wins.
    Map<String, String> testEnv = new HashMap<>();
    for (Map.Entry<String, String> entry : options.testEnvironment) {
      testEnv.put(entry.getKey(), entry.getValue());
    }
    return ActionEnvironment.split(testEnv);
  }

  // Only BuildConfigurationFunction should instantiate this.
  public static BuildConfigurationValue create(
      BuildOptions buildOptions,
      @Nullable BuildOptions baselineOptions,
      String workspaceName,
      boolean siblingRepositoryLayout,
      // Arguments below this are server-global.
      BlazeDirectories directories,
      GlobalStateProvider globalProvider,
      FragmentFactory fragmentFactory)
      throws InvalidConfigurationException {

    FragmentClassSet fragmentClasses =
        buildOptions.hasNoConfig()
            ? FragmentClassSet.of(ImmutableSet.of())
            : globalProvider.getFragmentRegistry().getAllFragments();
    ImmutableSortedMap<Class<? extends Fragment>, Fragment> fragments =
        getConfigurationFragments(buildOptions, fragmentClasses, fragmentFactory);

    String mnemonic =
        OutputPathMnemonicComputer.computeMnemonic(buildOptions, baselineOptions, fragments);

    return new BuildConfigurationValue(
        buildOptions,
        mnemonic,
        workspaceName,
        siblingRepositoryLayout,
        directories,
        fragments,
        globalProvider.getReservedActionMnemonics(),
        globalProvider.getActionEnvironment(buildOptions));
  }

  // TODO(blaze-configurability-team): Ideally tests use the above create; however,
  //   ConfigurationTestCase most just checks equality constraints and this wants to directly
  //   fiddle with the mnemonic (and supplying a baselineOptions would be somewhat heavy).
  @VisibleForTesting
  public static BuildConfigurationValue createForTesting(
      BuildOptions buildOptions,
      String mnemonic,
      String workspaceName,
      boolean siblingRepositoryLayout,
      // Arguments below this are server-global.
      BlazeDirectories directories,
      GlobalStateProvider globalProvider,
      FragmentFactory fragmentFactory)
      throws InvalidConfigurationException {

    FragmentClassSet fragmentClasses =
        buildOptions.hasNoConfig()
            ? FragmentClassSet.of(ImmutableSet.of())
            : globalProvider.getFragmentRegistry().getAllFragments();
    ImmutableSortedMap<Class<? extends Fragment>, Fragment> fragments =
        getConfigurationFragments(buildOptions, fragmentClasses, fragmentFactory);

    return new BuildConfigurationValue(
        buildOptions,
        mnemonic,
        workspaceName,
        siblingRepositoryLayout,
        directories,
        fragments,
        globalProvider.getReservedActionMnemonics(),
        globalProvider.getActionEnvironment(buildOptions));
  }

  private static ImmutableSortedMap<Class<? extends Fragment>, Fragment> getConfigurationFragments(
      BuildOptions buildOptions, FragmentClassSet fragmentClasses, FragmentFactory fragmentFactory)
      throws InvalidConfigurationException {
    ImmutableSortedMap.Builder<Class<? extends Fragment>, Fragment> fragments =
        ImmutableSortedMap.orderedBy(FragmentClassSet.LEXICAL_FRAGMENT_SORTER);
    for (Class<? extends Fragment> fragmentClass : fragmentClasses) {
      Fragment fragment = fragmentFactory.createFragment(buildOptions, fragmentClass);
      if (fragment != null) {
        fragments.put(fragmentClass, fragment);
      }
    }
    return fragments.buildOrThrow();
  }

  // Package-visible for serialization purposes.
  BuildConfigurationValue(
      BuildOptions buildOptions,
      String mnemonic,
      String workspaceName,
      boolean siblingRepositoryLayout,
      // Arguments below this are either server-global and constant or completely dependent values.
      BlazeDirectories directories,
      ImmutableMap<Class<? extends Fragment>, Fragment> fragments,
      ImmutableSet<String> reservedActionMnemonics,
      ActionEnvironment actionEnvironment) {
    this.fragments =
        fragmentsInterner.intern(
            ImmutableSortedMap.copyOf(fragments, FragmentClassSet.LEXICAL_FRAGMENT_SORTER));
    this.starlarkVisibleFragments = buildIndexOfStarlarkVisibleFragments();
    this.buildOptions = buildOptions;
    this.mnemonic = mnemonic;
    this.options = buildOptions.get(CoreOptions.class);
    PlatformOptions platformOptions = null;
    if (buildOptions.contains(PlatformOptions.class)) {
      platformOptions = buildOptions.get(PlatformOptions.class);
    }
    this.outputDirectories =
        new OutputDirectories(
            directories,
            options,
            platformOptions,
            mnemonic,
            workspaceName,
            siblingRepositoryLayout);
    this.workspaceName = workspaceName;
    this.siblingRepositoryLayout = siblingRepositoryLayout;

    // We can't use an ImmutableMap.Builder here; we need the ability to add entries with keys that
    // are already in the map so that the same define can be specified on the command line twice,
    // and ImmutableMap.Builder does not support that.
    commandLineBuildVariables =
        ImmutableMap.copyOf(options.getNormalizedCommandLineBuildVariables());

    this.actionEnv = actionEnvironment;
    this.testEnv = setupTestEnvironment();
    this.buildOptionDetails =
        BuildOptionDetails.forOptions(
            buildOptions.getNativeOptions(), buildOptions.getStarlarkOptions());

    // These should be documented in the build encyclopedia.
    // TODO(configurability-team): Deprecate TARGET_CPU in favor of platforms.
    globalMakeEnv =
        ImmutableMap.of(
            "TARGET_CPU",
            options.cpu,
            "COMPILATION_MODE",
            options.compilationMode.toString(),
            "BINDIR",
            getBinDirectory(RepositoryName.MAIN).getExecPathString(),
            "GENDIR",
            getGenfilesDirectory(RepositoryName.MAIN).getExecPathString());

    this.reservedActionMnemonics = reservedActionMnemonics;
    this.commandLineLimits = new CommandLineLimits(options.minParamFileSize);
    this.defaultFeatures = FeatureSet.parse(options.defaultFeatures);
  }

  @Override
  public boolean equals(Object other) {
    if (this == other) {
      return true;
    }
    if (!(other instanceof BuildConfigurationValue otherVal)) {
      return false;
    }
    // Only considering arguments that are non-dependent and non-server-global.
    return this.buildOptions.equals(otherVal.buildOptions)
        && this.workspaceName.equals(otherVal.workspaceName)
        && this.siblingRepositoryLayout == otherVal.siblingRepositoryLayout
        && this.mnemonic.equals(otherVal.mnemonic);
  }

  @Override
  public int hashCode() {
    return Objects.hash(buildOptions, workspaceName, siblingRepositoryLayout, mnemonic);
  }

  private ImmutableMap<String, Class<? extends Fragment>> buildIndexOfStarlarkVisibleFragments() {
    ImmutableMap.Builder<String, Class<? extends Fragment>> builder = ImmutableMap.builder();

    for (Class<? extends Fragment> fragmentClass : fragments.keySet()) {
      StarlarkBuiltin module = StarlarkAnnotations.getStarlarkBuiltin(fragmentClass);
      if (module != null) {
        builder.put(module.name(), fragmentClass);
      }
    }
    return builder.buildOrThrow();
  }

  /**
   * Returns the {@link BuildConfigurationKey} for this configuration.
   *
   * <p>Note that this method does not apply a platform mapping. It is assumed that this
   * configuration was created with a platform mapping and thus its key does not need to be mapped
   * again.
   */
  public BuildConfigurationKey getKey() {
    return BuildConfigurationKey.create(buildOptions);
  }

  /** Retrieves the {@link BuildOptionDetails} containing data on this configuration's options. */
  public BuildOptionDetails getBuildOptionDetails() {
    return buildOptionDetails;
  }

  /** Returns the output directory for this build configuration. */
  public ArtifactRoot getOutputDirectory(RepositoryName repositoryName) {
    return outputDirectories.getOutputDirectory(repositoryName);
  }

  /** @deprecated Use {@link #getBinDirectory} instead. */
  @Override
  @Deprecated
  public ArtifactRoot getBinDir() {
    return outputDirectories.getBinDirectory(RepositoryName.MAIN);
  }

  /**
   * Returns the bin directory for this build configuration.
   *
   * <p>TODO(kchodorow): This (and the other get*Directory functions) won't work with external
   * repositories without changes to how ArtifactFactory resolves derived roots. This is not an
   * issue right now because it only effects Blaze's include scanning (internal) and Bazel's
   * repositories (external) but will need to be fixed.
   *
   * @deprecated Use {@code RuleContext#getBinDirectory} instead whenever possible.
   */
  @Deprecated
  public ArtifactRoot getBinDirectory(RepositoryName repositoryName) {
    return outputDirectories.getBinDirectory(repositoryName);
  }

  /**
   * Returns a relative path to the bin directory at execution time.
   *
   * @deprecated Use {@code RuleContext#getBinFragment} instead whenever possible.
   */
  @Deprecated
  public PathFragment getBinFragment(RepositoryName repositoryName) {
    return outputDirectories.getBinDirectory(repositoryName).getExecPath();
  }

  /** @deprecated Use {@link #getGenfilesDirectory} instead. */
  @Override
  @Deprecated
  public ArtifactRoot getGenfilesDir() {
    return outputDirectories.getGenfilesDirectory(RepositoryName.MAIN);
  }

  /**
   * Returns the genfiles directory for this build configuration.
   *
   * @deprecated Use {@code RuleContext#getGenfilesDirectory} instead whenever possible.
   */
  @Deprecated
  public ArtifactRoot getGenfilesDirectory(RepositoryName repositoryName) {
    return outputDirectories.getGenfilesDirectory(repositoryName);
  }

  public boolean hasSeparateGenfilesDirectory() {
    return !outputDirectories.mergeGenfilesDirectory();
  }

  @Override
  public boolean hasSeparateGenfilesDirectoryForStarlark(StarlarkThread thread)
      throws EvalException {
    BuiltinRestriction.failIfCalledOutsideBuiltins(thread);
    return hasSeparateGenfilesDirectory();
  }

  /**
   * Returns the directory where coverage-related artifacts and metadata files should be stored.
   * This includes for example uninstrumented class files needed for Jacoco's coverage reporting
   * tools.
   *
   * @deprecated Use {@code RuleContext#getCoverageMetadataDirectory} instead whenever possible.
   */
  @Deprecated
  public ArtifactRoot getCoverageMetadataDirectory(RepositoryName repositoryName) {
    return outputDirectories.getCoverageMetadataDirectory(repositoryName);
  }

  /**
   * Returns the testlogs directory for this build configuration.
   *
   * <p>Use {@code RuleContext#getTestLogsDirectory} instead whenever possible.
   */
  public ArtifactRoot getTestLogsDirectory(RepositoryName repositoryName) {
    return outputDirectories.getTestLogsDirectory(repositoryName);
  }

  /**
   * Returns a relative path to the genfiles directory at execution time.
   *
   * @deprecated Use {@code RuleContext#getGenfilesFragment} instead whenever possible.
   */
  @Deprecated
  public PathFragment getGenfilesFragment(RepositoryName repositoryName) {
    return outputDirectories.getGenfilesFragment(repositoryName);
  }

  /**
   * Returns the path separator for the host platform. This is basically the same as {@link
   * java.io.File#pathSeparator}, except that that returns the value for this JVM, which may or may
   * not match the host platform. You should only use this when invoking tools that are known to use
   * the native path separator, i.e., the path separator for the machine that they run on.
   */
  @Override
  public String getHostPathSeparator() {
    return outputDirectories.getHostPathSeparator();
  }

  /**
   * Returns the internal directory (used for middlemen) for this build configuration.
   *
   * @deprecated Use {@code RuleContext#getMiddlemanDirectory} instead whenever possible.
   */
  @Deprecated
  public ArtifactRoot getMiddlemanDirectory(RepositoryName repositoryName) {
    return outputDirectories.getMiddlemanDirectory(repositoryName);
  }

  public boolean isStrictFilesets() {
    return options.strictFilesets;
  }

  public boolean isStrictFilesetOutput() {
    return options.strictFilesetOutput;
  }

  public String getWorkspaceName() {
    return workspaceName;
  }

  @Override
  public String getMnemonic() {
    return outputDirectories.getMnemonic();
  }

  /** Returns whether to use automatic exec groups. */
  public boolean useAutoExecGroups() {
    return options.useAutoExecGroups;
  }

  /**
   * Returns the name of the base output directory under which actions in this configuration write
   * their outputs.
   *
   * <p>This is the same as {@link #getMnemonic}.
   */
  public String getOutputDirectoryName() {
    return outputDirectories.getOutputDirName();
  }

  @Override
  public String toString() {
    return checksum();
  }

  @Override
  public void debugPrint(PrintStream out) {
    out.printf("BuildConfigurationValue: %s\n", this.checksum());
    out.printf("  %s\n", this.options);
  }

  public ActionEnvironment getActionEnvironment() {
    return actionEnv;
  }

  public boolean isSiblingRepositoryLayout() {
    return siblingRepositoryLayout;
  }

  @Override
  public boolean isSiblingRepositoryLayoutForStarlark(StarlarkThread thread) throws EvalException {
    BuiltinRestriction.failIfCalledOutsideBuiltins(thread);
    return isSiblingRepositoryLayout();
  }

  /**
   * Return the "fixed" part of the actions' environment variables.
   *
   * <p>An action's full set of environment variables consist of a "fixed" part and of a "variable"
   * part. The "fixed" variables are independent of the Bazel client's own environment, and are
   * returned by this function. The "variable" ones are inherited from the Bazel client's own
   * environment, and are returned by {@link #getVariableShellEnvironment}.
   *
   * <p>Since values of the "fixed" variables are already known at analysis phase, it is returned
   * here as a map.
   */
  @Override
  public ImmutableMap<String, String> getLocalShellEnvironment() {
    return actionEnv.getFixedEnv();
  }

  /**
   * Return the "variable" part of the actions' environment variables.
   *
   * <p>An action's full set of environment variables consist of a "fixed" part and of a "variable"
   * part. The "fixed" variables are independent of the Bazel client's own environment, and are
   * returned by {@link #getLocalShellEnvironment}. The "variable" ones are inherited from the Bazel
   * client's own environment, and are returned by this function.
   *
   * <p>The values of the "variable" variables are tracked in Skyframe via the {@link
   * com.google.devtools.build.lib.skyframe.SkyFunctions#CLIENT_ENVIRONMENT_VARIABLE} skyfunction.
   * This method only returns the names of those variables to be inherited, if set in the client's
   * environment. (Variables where the name is not returned in this set should not be taken from the
   * client environment.)
   */
  @Deprecated // Use getActionEnvironment instead.
  public Iterable<String> getVariableShellEnvironment() {
    return actionEnv.getInheritedEnv();
  }

  /**
   * Returns a regex-based instrumentation filter instance that used to match label names to
   * identify targets to be instrumented in the coverage mode.
   */
  public RegexFilter getInstrumentationFilter() {
    return options.instrumentationFilter;
  }

  /**
   * Returns a boolean of whether to include targets created by *_test rules in the set of targets
   * matched by --instrumentation_filter. If this is false, all test targets are excluded from
   * instrumentation.
   */
  public boolean shouldInstrumentTestTargets() {
    return options.instrumentTestTargets;
  }

  /** Returns a boolean of whether to collect code coverage for generated files or not. */
  public boolean shouldCollectCodeCoverageForGeneratedFiles() {
    return options.collectCodeCoverageForGeneratedFiles;
  }

  /**
   * Returns a new, unordered mapping of names to values of "Make" variables defined by this
   * configuration.
   *
   * <p>This does *not* include package-defined overrides (e.g. vardef) and so should not be used by
   * the build logic. This is used only for the 'info' command.
   *
   * <p>Command-line definitions of make environments override variables defined by {@code
   * Fragment.addGlobalMakeVariables()}.
   */
  public Map<String, String> getMakeEnvironment() {
    Map<String, String> makeEnvironment = new HashMap<>();
    makeEnvironment.putAll(globalMakeEnv);
    makeEnvironment.putAll(commandLineBuildVariables);
    return ImmutableMap.copyOf(makeEnvironment);
  }

  /**
   * Returns a new, unordered mapping of names that are set through the command lines. (Fragments,
   * in particular the Google C++ support, can set variables through the command line.)
   */
  public ImmutableMap<String, String> getCommandLineBuildVariables() {
    return commandLineBuildVariables;
  }

  /** Returns the global defaults for this configuration for the Make environment. */
  public ImmutableMap<String, String> getGlobalMakeEnvironment() {
    return globalMakeEnv;
  }

  /**
   * Returns the default value for the specified "Make" variable for this configuration. Returns
   * null if no value was found.
   */
  public String getMakeVariableDefault(String var) {
    return globalMakeEnv.get(var);
  }

  /** Returns a configuration fragment instances of the given class. */
  public <T extends Fragment> T getFragment(Class<T> clazz) {
    return clazz.cast(fragments.get(clazz));
  }

  /** Return all the configuration fragments. */
  public ImmutableSortedMap<Class<? extends Fragment>, Fragment> getFragments() {
    return fragments;
  }

  /** Returns true if the requested configuration fragment is present. */
  public <T extends Fragment> boolean hasFragment(Class<T> clazz) {
    return getFragment(clazz) != null;
  }

  /** Returns true if all requested configuration fragment are present (this may be slow). */
  public boolean hasAllFragments(Set<Class<?>> fragmentClasses) {
    for (Class<?> fragmentClass : fragmentClasses) {
      if (!hasFragment(fragmentClass.asSubclass(Fragment.class))) {
        return false;
      }
    }
    return true;
  }

  public BlazeDirectories getDirectories() {
    return outputDirectories.getDirectories();
  }

  /** Returns true if non-functional build stamps are enabled. */
  public boolean stampBinaries() {
    return options.stampBinaries;
  }

  @Override
  public boolean stampBinariesForStarlark(StarlarkThread thread) throws EvalException {
    BuiltinRestriction.failIfCalledOutsideBuiltins(thread);
    return stampBinaries();
  }

  /** Returns true if extended sanity checks should be enabled. */
  public boolean extendedSanityChecks() {
    return options.extendedSanityChecks;
  }

  /** Returns true if we are building runfiles manifests for this configuration. */
  public boolean buildRunfileManifests() {
    return options.buildRunfileManifests;
  }

  /** Returns true if we are building runfile links for this configuration. */
  public boolean buildRunfileLinks() {
    return options.buildRunfileManifests && options.buildRunfileLinks;
  }

  /** Returns if we are building external runfiles symlinks using the old-style structure. */
  public boolean legacyExternalRunfiles() {
    return options.legacyExternalRunfiles;
  }

  /**
   * Returns true if Runfiles should merge in FilesToBuild from deps when collecting data runfiles.
   */
  public boolean alwaysIncludeFilesToBuildInData() {
    return options.alwaysIncludeFilesToBuildInData;
  }

  /**
   * Returns user-specified test environment variables and their values, as set by the --test_env
   * options.
   */
  @Override
  public ImmutableMap<String, String> getTestEnv() {
    return testEnv.getFixedEnv();
  }

  /**
   * Returns user-specified test environment variables and their values, as set by the {@code
   * --test_env} options. It is incomplete in that it is not a superset of the {@link
   * #getActionEnvironment}, but both have to be applied, with this one being applied after the
   * other, such that {@code --test_env} settings can override {@code --action_env} settings.
   */
  // TODO(ulfjack): Just return the merged action and test action environment here?
  public ActionEnvironment getTestActionEnvironment() {
    return testEnv;
  }

  @Override
  public CommandLineLimits getCommandLineLimits() {
    return commandLineLimits;
  }

  @Override
  public boolean isCodeCoverageEnabled() {
    return options.collectCodeCoverage;
  }

  public RunUnder getRunUnder() {
    return options.runUnder;
  }

  /** Returns true if this is an execution configuration. */
  public boolean isExecConfiguration() {
    return options.isExec;
  }

  @Override
  public boolean isToolConfiguration() {
    return isExecConfiguration();
  }

  @Override
  public boolean isToolConfigurationForStarlark(StarlarkThread thread) throws EvalException {
    BuiltinRestriction.failIfCalledOutsideAllowlist(thread, ANDROID_ALLOWLIST);
    return isToolConfiguration();
  }

  public boolean checkVisibility() {
    return options.checkVisibility;
  }

  public boolean checkTestonlyForOutputFiles() {
    return options.checkTestonlyForOutputFiles;
  }

  public boolean checkLicenses() {
    return options.checkLicenses;
  }

  public boolean enforceConstraints() {
    return options.enforceConstraints;
  }

  public boolean allowAnalysisFailures() {
    return options.allowAnalysisFailures;
  }

  public boolean evaluatingForAnalysisTest() {
    return options.evaluatingForAnalysisTest;
  }

  public int analysisTestingDepsLimit() {
    return options.analysisTestingDepsLimit;
  }

  public List<Label> getActionListeners() {
    return options.actionListeners;
  }

  /**
   * <b>>Experimental feature:</b> if true, qualifying outputs use path prefixes based on their
   * content instead of the traditional <code>blaze-out/$CPU-$COMPILATION_MODE</code>.
   *
   * <p>This promises both more intrinsic correctness (outputs with different contents can't write
   * to the same path) and efficiency (outputs with the <i>same</i> contents share the same path and
   * therefore permit better action caching). But it's highly experimental and should not be relied
   * on in any serious way any time soon.
   *
   * <p>See <a href="https://github.com/bazelbuild/bazel/issues/6526">#6526</a> for details.
   */
  public boolean useContentBasedOutputPaths() {
    return options.outputPathsMode == CoreOptions.OutputPathsMode.CONTENT;
  }

  public boolean allowUnresolvedSymlinks() {
    return options.allowUnresolvedSymlinks;
  }

  /** Returns compilation mode. */
  public CompilationMode getCompilationMode() {
    return options.compilationMode;
  }

  @Override
  public String checksum() {
    return buildOptions.checksum();
  }

  /**
   * Returns a user-friendly short configuration identifier.
   *
   * <p>See {@link BuildOptions#shortId()} for details.
   */
  public String shortId() {
    return buildOptions.shortId();
  }

  /** Returns a copy of the build configuration options for this configuration. */
  public BuildOptions cloneOptions() {
    return buildOptions.clone();
  }

  /**
   * Returns the actual options reference used by this configuration.
   *
   * <p><b>Be very careful using this method.</b> Options classes are mutable - no caller should
   * ever call this method if there's any change the reference might be written to. This method only
   * exists because {@link #cloneOptions} can be expensive when applied to every edge in a
   * dependency graph.
   *
   * <p>Do not use this method without careful review with other Bazel developers.
   */
  public BuildOptions getOptions() {
    return buildOptions;
  }

  public String getCpu() {
    return options.cpu;
  }

  @VisibleForTesting
  public String getHostCpu() {
    return options.hostCpu;
  }

  /**
   * Describes how to create runfile symlink trees.
   *
   * <p>May be overridden if an {@link com.google.devtools.build.lib.vfs.OutputService} capable of
   * creating symlink trees is available.
   */
  public enum RunfileSymlinksMode {
    /** Do not create. */
    SKIP,
    /** Use the out-of-process implementation. */
    EXTERNAL,
    /** Use the in-process implementation. */
    INTERNAL
  }

  @VisibleForTesting
  public static RunfileSymlinksMode getRunfileSymlinksMode(CoreOptions options) {
    // TODO(buchgr): Revisit naming and functionality of this flag. See #9248 for details.
    if (options.enableRunfiles == TriState.YES
        || (options.enableRunfiles == TriState.AUTO && OS.getCurrent() != OS.WINDOWS)) {
      return options.inProcessSymlinkCreation
          ? RunfileSymlinksMode.INTERNAL
          : RunfileSymlinksMode.EXTERNAL;
    }
    return RunfileSymlinksMode.SKIP;
  }

  public RunfileSymlinksMode getRunfileSymlinksMode() {
    return getRunfileSymlinksMode(options);
  }

  public static boolean runfilesEnabled(CoreOptions options) {
    return getRunfileSymlinksMode(options) != RunfileSymlinksMode.SKIP;
  }

  public boolean runfilesEnabled() {
    return runfilesEnabled(options);
  }

  @Override
  public boolean runfilesEnabledForStarlark(StarlarkThread thread) throws EvalException {
    BuiltinRestriction.failIfCalledOutsideBuiltins(thread);
    return runfilesEnabled();
  }

  public boolean remotableSourceManifestActions() {
    return options.remotableSourceManifestActions;
  }

  /**
   * Returns a modified copy of {@code executionInfo} if any {@code executionInfoModifiers} apply to
   * the given {@code mnemonic}. Otherwise returns {@code executionInfo} unchanged.
   */
  public ImmutableMap<String, String> modifiedExecutionInfo(
      ImmutableMap<String, String> executionInfo, String mnemonic) {
    if (!options.executionInfoModifier.matches(mnemonic)) {
      return executionInfo;
    }
    Map<String, String> mutableCopy = new HashMap<>(executionInfo);
    modifyExecutionInfo(mutableCopy, mnemonic);
    return ImmutableSortedMap.copyOf(mutableCopy);
  }

  /** Applies {@code executionInfoModifiers} to the given {@code executionInfo}. */
  public void modifyExecutionInfo(Map<String, String> executionInfo, String mnemonic) {
    options.executionInfoModifier.apply(mnemonic, executionInfo);
  }

  /** Returns the list of default features used for all packages. */
  public FeatureSet getDefaultFeatures() {
    return defaultFeatures;
  }

  /**
   * Returns the "top-level" environment space, i.e. the set of environments all top-level targets
   * must be compatible with. An empty value implies no restrictions.
   */
  public List<Label> getTargetEnvironments() {
    return options.targetEnvironments;
  }

  @Nullable
  public Class<? extends Fragment> getStarlarkFragmentByName(String name) {
    return starlarkVisibleFragments.get(name);
  }

  public ImmutableCollection<String> getStarlarkFragmentNames() {
    return starlarkVisibleFragments.keySet();
  }

  public BuildEventId getEventId() {
    return BuildEventIdUtil.configurationId(checksum());
  }

  @Override
  public BuildConfigurationEvent toBuildEvent() {
    if (buildEvent == null) {
      synchronized (this) {
        if (buildEvent == null) {
          buildEvent = createBuildEvent();
        }
      }
    }
    return buildEvent;
  }

  private BuildConfigurationEvent createBuildEvent() {
    BuildEventId eventId = getEventId();
    BuildEventStreamProtos.BuildEvent.Builder builder =
        BuildEventStreamProtos.BuildEvent.newBuilder();
    builder
        .setId(eventId)
        .setConfiguration(
            BuildEventStreamProtos.Configuration.newBuilder()
                .setMnemonic(getMnemonic())
                .setPlatformName(getCpu())
                .putAllMakeVariable(getMakeEnvironment())
                .setCpu(getCpu())
                .setIsTool(isToolConfiguration())
                .build());
    return new BuildConfigurationEvent(eventId, builder.build());
  }

  public static BuildEventId.ConfigurationId configurationIdMessage(
      @Nullable BuildConfigurationValue configuration) {
    if (configuration == null) {
      return BuildEventIdUtil.nullConfigurationIdMessage();
    }
    return BuildEventIdUtil.configurationIdMessage(configuration.checksum());
  }

  public static BuildEventId configurationId(@Nullable BuildConfigurationValue configuration) {
    if (configuration == null) {
      return BuildEventIdUtil.nullConfigurationId();
    }
    return configuration.getEventId();
  }

  public static BuildEvent buildEvent(@Nullable BuildConfigurationValue configuration) {
    return configuration == null ? NullConfiguration.INSTANCE : configuration.toBuildEvent();
  }

  public ImmutableSet<String> getReservedActionMnemonics() {
    return reservedActionMnemonics;
  }
}
