// 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.cpp;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.devtools.build.lib.actions.ActionOwner;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.actions.Artifact.TreeFileArtifact;
import com.google.devtools.build.lib.actions.MiddlemanFactory;
import com.google.devtools.build.lib.analysis.AnalysisUtils;
import com.google.devtools.build.lib.analysis.TransitiveInfoCollection;
import com.google.devtools.build.lib.analysis.actions.ActionConstructionContext;
import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.collect.compacthashset.CompactHashSet;
import com.google.devtools.build.lib.collect.nestedset.Depset;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
import com.google.devtools.build.lib.collect.nestedset.Order;
import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
import com.google.devtools.build.lib.rules.cpp.IncludeScanner.IncludeScanningHeaderData;
import com.google.devtools.build.lib.skyframe.TreeArtifactValue;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec.VisibleForSerialization;
import com.google.devtools.build.lib.skylarkbuildapi.cpp.CcCompilationContextApi;
import com.google.devtools.build.lib.syntax.StarlarkList;
import com.google.devtools.build.lib.util.Pair;
import com.google.devtools.build.lib.vfs.PathFragment;
import com.google.devtools.build.skyframe.SkyFunction.Environment;
import com.google.devtools.build.skyframe.SkyKey;
import com.google.devtools.build.skyframe.SkyValue;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;

/**
 * Immutable store of information needed for C++ compilation that is aggregated across dependencies.
 */
@Immutable
@AutoCodec
public final class CcCompilationContext implements CcCompilationContextApi<Artifact> {
  /** An empty {@code CcCompilationContext}. */
  public static final CcCompilationContext EMPTY =
      builder(/* actionConstructionContext= */ null, /* configuration= */ null, /* label= */ null)
          .build();

  private final CommandLineCcCompilationContext commandLineCcCompilationContext;

  private final NestedSet<PathFragment> looseHdrsDirs;
  private final NestedSet<Artifact> declaredIncludeSrcs;

  /** Module maps from direct dependencies. */
  private final ImmutableList<Artifact> directModuleMaps;

  /** Module maps from dependencies that will be re-exported by this compilation context. */
  private final ImmutableList<CppModuleMap> exportingModuleMaps;

  /** Non-code mandatory compilation inputs. */
  private final NestedSet<Artifact> nonCodeInputs;

  private final HeaderInfo headerInfo;
  private final NestedSet<HeaderInfo> transitiveHeaderInfos;
  private final NestedSet<Artifact> transitiveModules;
  private final NestedSet<Artifact> transitivePicModules;

  private final CppModuleMap cppModuleMap;
  private final CppModuleMap verificationModuleMap;

  private final boolean propagateModuleMapAsActionInput;

  // Derived from depsContexts.
  private final NestedSet<Artifact> compilationPrerequisites;

  private final CppConfiguration.HeadersCheckingMode headersCheckingMode;

  // Each pair maps the Bazel generated paths of virtual include headers back to their original path
  // relative to the workspace directory.
  // For example it can map
  // "bazel-out/k8-fastbuild/bin/include/common/_virtual_includes/strategy/strategy.h"
  // back to the path of the header in the workspace directory "include/common/strategy.h".
  // This is needed only when code coverage collection is enabled, to report the actual source file
  // name in the coverage output file.
  private final NestedSet<Pair<String, String>> virtualToOriginalHeaders;

  @AutoCodec.Instantiator
  @VisibleForSerialization
  CcCompilationContext(
      CommandLineCcCompilationContext commandLineCcCompilationContext,
      NestedSet<Artifact> compilationPrerequisites,
      NestedSet<PathFragment> looseHdrsDirs,
      NestedSet<Artifact> declaredIncludeSrcs,
      NestedSet<Artifact> nonCodeInputs,
      HeaderInfo headerInfo,
      NestedSet<HeaderInfo> transitiveHeaderInfos,
      NestedSet<Artifact> transitiveModules,
      NestedSet<Artifact> transitivePicModules,
      ImmutableList<Artifact> directModuleMaps,
      ImmutableList<CppModuleMap> exportingModuleMaps,
      CppModuleMap cppModuleMap,
      @Nullable CppModuleMap verificationModuleMap,
      boolean propagateModuleMapAsActionInput,
      CppConfiguration.HeadersCheckingMode headersCheckingMode,
      NestedSet<Pair<String, String>> virtualToOriginalHeaders) {
    Preconditions.checkNotNull(commandLineCcCompilationContext);
    this.commandLineCcCompilationContext = commandLineCcCompilationContext;
    this.looseHdrsDirs = looseHdrsDirs;
    this.declaredIncludeSrcs = declaredIncludeSrcs;
    this.directModuleMaps = directModuleMaps;
    this.exportingModuleMaps = exportingModuleMaps;
    this.headerInfo = headerInfo;
    this.transitiveHeaderInfos = transitiveHeaderInfos;
    this.transitiveModules = transitiveModules;
    this.transitivePicModules = transitivePicModules;
    this.cppModuleMap = cppModuleMap;
    this.nonCodeInputs = nonCodeInputs;
    this.verificationModuleMap = verificationModuleMap;
    this.compilationPrerequisites = compilationPrerequisites;
    this.propagateModuleMapAsActionInput = propagateModuleMapAsActionInput;
    this.headersCheckingMode = headersCheckingMode;
    this.virtualToOriginalHeaders = virtualToOriginalHeaders;
  }

  @Override
  public boolean isImmutable() {
    return true; // immutable and Starlark-hashable
  }

  @Override
  public Depset getStarlarkDefines() {
    return Depset.of(Depset.ElementType.STRING, getDefines());
  }

  @Override
  public Depset getStarlarkNonTransitiveDefines() {
    return Depset.of(
        Depset.ElementType.STRING,
        NestedSetBuilder.wrap(Order.STABLE_ORDER, getNonTransitiveDefines()));
  }

  @Override
  public Depset getStarlarkHeaders() {
    return Depset.of(Artifact.TYPE, getDeclaredIncludeSrcs());
  }

  @Override
  public StarlarkList<Artifact> getStarlarkDirectModularHeaders() {
    return StarlarkList.immutableCopyOf(getDirectHdrs());
  }

  @Override
  public StarlarkList<Artifact> getStarlarkDirectTextualHeaders() {
    return StarlarkList.immutableCopyOf(getTextualHdrs());
  }

  @Override
  public Depset getStarlarkSystemIncludeDirs() {
    return Depset.of(
        Depset.ElementType.STRING,
        NestedSetBuilder.wrap(
            Order.STABLE_ORDER,
            getSystemIncludeDirs().stream()
                .map(PathFragment::getSafePathString)
                .collect(ImmutableList.toImmutableList())));
  }

  @Override
  public Depset getStarlarkFrameworkIncludeDirs() {
    return Depset.of(
        Depset.ElementType.STRING,
        NestedSetBuilder.wrap(
            Order.STABLE_ORDER,
            getFrameworkIncludeDirs().stream()
                .map(PathFragment::getSafePathString)
                .collect(ImmutableList.toImmutableList())));
  }

  @Override
  public Depset getStarlarkIncludeDirs() {
    return Depset.of(
        Depset.ElementType.STRING,
        NestedSetBuilder.wrap(
            Order.STABLE_ORDER,
            getIncludeDirs().stream()
                .map(PathFragment::getSafePathString)
                .collect(ImmutableList.toImmutableList())));
  }

  @Override
  public Depset getStarlarkQuoteIncludeDirs() {
    return Depset.of(
        Depset.ElementType.STRING,
        NestedSetBuilder.wrap(
            Order.STABLE_ORDER,
            getQuoteIncludeDirs().stream()
                .map(PathFragment::getSafePathString)
                .collect(ImmutableList.toImmutableList())));
  }

  /**
   * Returns the transitive compilation prerequisites consolidated into middlemen prerequisites, or
   * an empty set if there are no prerequisites.
   *
   * <p>Transitive compilation prerequisites are the prerequisites that will be needed by all
   * reverse dependencies; note that these do specifically not include any compilation prerequisites
   * that are only needed by the rule itself (for example, compiled source files from the {@code
   * srcs} attribute).
   *
   * <p>To reduce the number of edges in the action graph, we express the dependency on compilation
   * prerequisites as a transitive dependency via a middleman. After they have been accumulated
   * ({@link Builder#mergeDependentCcCompilationContext(CcCompilationContext)}, and {@link
   * Builder#mergeDependentCcCompilationContexts(Iterable)}, they are consolidated into a single
   * middleman Artifact when {@link Builder#build()} is called.
   *
   * <p>The returned set can be empty if there are no prerequisites. Usually, it contains a single
   * middleman.
   */
  public NestedSet<Artifact> getTransitiveCompilationPrerequisites() {
    return compilationPrerequisites;
  }

  /**
   * Returns the immutable list of include directories to be added with "-I" (possibly empty but
   * never null). This includes the include dirs from the transitive deps closure of the target.
   * This list does not contain duplicates. All fragments are either absolute or relative to the
   * exec root (see {@link
   * com.google.devtools.build.lib.analysis.BlazeDirectories#getExecRoot(String)}).
   */
  public ImmutableList<PathFragment> getIncludeDirs() {
    return commandLineCcCompilationContext.includeDirs;
  }

  /**
   * Returns the immutable list of include directories to be added with "-iquote" (possibly empty
   * but never null). This includes the include dirs from the transitive deps closure of the target.
   * This list does not contain duplicates. All fragments are either absolute or relative to the
   * exec root (see {@link
   * com.google.devtools.build.lib.analysis.BlazeDirectories#getExecRoot(String)}).
   */
  public ImmutableList<PathFragment> getQuoteIncludeDirs() {
    return commandLineCcCompilationContext.quoteIncludeDirs;
  }

  /**
   * Returns the immutable list of include directories to be added with "-isystem" (possibly empty
   * but never null). This includes the include dirs from the transitive deps closure of the target.
   * This list does not contain duplicates. All fragments are either absolute or relative to the
   * exec root (see {@link
   * com.google.devtools.build.lib.analysis.BlazeDirectories#getExecRoot(String)}).
   */
  public ImmutableList<PathFragment> getSystemIncludeDirs() {
    return commandLineCcCompilationContext.systemIncludeDirs;
  }

  /**
   * Returns the immutable list of include directories to be added with "-F" (possibly empty but
   * never null). This includes the include dirs from the transitive deps closure of the target.
   * This list does not contain duplicates. All fragments are either absolute or relative to the
   * exec root (see {@link com.google.devtools.build.lib.analysis.BlazeDirectories#getExecRoot}).
   */
  public ImmutableList<PathFragment> getFrameworkIncludeDirs() {
    return commandLineCcCompilationContext.frameworkIncludeDirs;
  }

  /**
   * Returns the immutable set of declared include directories, relative to a "-I" or "-iquote"
   * directory" (possibly empty but never null).
   */
  public NestedSet<PathFragment> getLooseHdrsDirs() {
    return looseHdrsDirs;
  }

  /**
   * Returns the immutable set of headers that have been declared in the {@code srcs} or {@code
   * hdrs} attribute (possibly empty but never null).
   */
  public NestedSet<Artifact> getDeclaredIncludeSrcs() {
    return declaredIncludeSrcs;
  }

  /** Returns headers given as textual_hdrs in this target. */
  public ImmutableList<Artifact> getTextualHdrs() {
    return headerInfo.textualHeaders;
  }

  /** Returns headers given as textual_hdrs in this target. */
  public ImmutableList<Artifact> getDirectHdrs() {
    return headerInfo.modularHeaders;
  }

  public ImmutableList<HeaderInfo> getTransitiveHeaderInfos() {
    return transitiveHeaderInfos.toList();
  }

  /** Helper class for creating include scanning header data. */
  public static class IncludeScanningHeaderDataHelper {
    private IncludeScanningHeaderDataHelper() {}

    public static void handleArtifact(
        Artifact artifact,
        Map<PathFragment, Artifact> pathToLegalOutputArtifact,
        ArrayList<Artifact> treeArtifacts) {
      if (artifact.isSourceArtifact()) {
        return;
      }
      if (artifact.isTreeArtifact()) {
        treeArtifacts.add(artifact);
        return;
      }
      pathToLegalOutputArtifact.put(artifact.getExecPath(), artifact);
    }

    /**
     * Enter the TreeArtifactValues in each TreeArtifact into pathToLegalOutputArtifact. Returns
     * true on success.
     *
     * <p>If a TreeArtifact's value is missing, returns false, and leave pathToLegalOutputArtifact
     * unmodified.
     */
    public static boolean handleTreeArtifacts(
        Environment env,
        Map<PathFragment, Artifact> pathToLegalOutputArtifact,
        ArrayList<Artifact> treeArtifacts)
        throws InterruptedException {
      if (!treeArtifacts.isEmpty()) {
        Map<SkyKey, SkyValue> valueMap = env.getValues(treeArtifacts);
        if (env.valuesMissing()) {
          return false;
        }
        for (SkyValue value : valueMap.values()) {
          Preconditions.checkState(value instanceof TreeArtifactValue);
          TreeArtifactValue treeArtifactValue = (TreeArtifactValue) value;
          for (TreeFileArtifact treeFileArtifact : treeArtifactValue.getChildren()) {
            pathToLegalOutputArtifact.put(treeFileArtifact.getExecPath(), treeFileArtifact);
          }
        }
      }
      return true;
    }
  }

  /**
   * This method returns null when a required SkyValue is missing and a Skyframe restart is
   * required.
   */
  @Nullable
  public IncludeScanningHeaderData.Builder createIncludeScanningHeaderData(
      Environment env,
      boolean usePic,
      boolean createModularHeaders,
      List<HeaderInfo> transitiveHeaderInfoList)
      throws InterruptedException {
    ArrayList<Artifact> treeArtifacts = new ArrayList<>();
    // We'd prefer for these types to use ImmutableSet/ImmutableMap. However, constructing these is
    // substantially more costly in a way that shows up in profiles.
    Map<PathFragment, Artifact> pathToLegalOutputArtifact = new HashMap<>();
    Set<Artifact> modularHeaders =
        CompactHashSet.createWithExpectedSize(transitiveHeaderInfoList.size());
    // Not using range-based for loops here and below as the additional overhead of the
    // ImmutableList iterators has shown up in profiles.
    for (int c = 0; c < transitiveHeaderInfoList.size(); c++) {
      HeaderInfo transitiveHeaderInfo = transitiveHeaderInfoList.get(c);
      boolean isModule = createModularHeaders && transitiveHeaderInfo.getModule(usePic) != null;
      for (int i = 0; i < transitiveHeaderInfo.modularHeaders.size(); i++) {
        Artifact a = transitiveHeaderInfo.modularHeaders.get(i);
        IncludeScanningHeaderDataHelper.handleArtifact(a, pathToLegalOutputArtifact, treeArtifacts);
        if (isModule) {
          modularHeaders.add(a);
        }
      }
      for (int i = 0; i < transitiveHeaderInfo.textualHeaders.size(); i++) {
        Artifact a = transitiveHeaderInfo.textualHeaders.get(i);
        IncludeScanningHeaderDataHelper.handleArtifact(a, pathToLegalOutputArtifact, treeArtifacts);
      }
    }
    if (!IncludeScanningHeaderDataHelper.handleTreeArtifacts(
        env, pathToLegalOutputArtifact, treeArtifacts)) {
      return null;
    }
    removeArtifactsFromSet(modularHeaders, headerInfo.modularHeaders);
    removeArtifactsFromSet(modularHeaders, headerInfo.textualHeaders);
    return new IncludeScanningHeaderData.Builder(
        Collections.unmodifiableMap(pathToLegalOutputArtifact),
        Collections.unmodifiableSet(modularHeaders));
  }

  /** Simple container for a collection of headers and corresponding modules. */
  public static class HeadersAndModules {
    public final Collection<Artifact> headers;
    public final Collection<Artifact.DerivedArtifact> modules;

    HeadersAndModules(int expectedHeaderCount) {
      headers = CompactHashSet.createWithExpectedSize(expectedHeaderCount);
      modules = CompactHashSet.create();
    }
  }

  /**
   * Returns a list of all headers from {@code includes} that are properly declared as well as all
   * the modules that they are in.
   */
  public HeadersAndModules computeDeclaredHeadersAndUsedModules(
      boolean usePic, Set<Artifact> includes, List<HeaderInfo> transitiveHeaderInfoList) {
    HeadersAndModules result = new HeadersAndModules(includes.size());
    for (int c = 0; c < transitiveHeaderInfoList.size(); c++) {
      HeaderInfo transitiveHeaderInfo = transitiveHeaderInfoList.get(c);
      Artifact.DerivedArtifact module = transitiveHeaderInfo.getModule(usePic);
      // Not using range-based for loops here as often there is exactly one element in this list
      // and the amount of garbage created by SingletonImmutableList.iterator() is significant.
      for (int i = 0; i < transitiveHeaderInfo.modularHeaders.size(); i++) {
        Artifact header = transitiveHeaderInfo.modularHeaders.get(i);
        if (includes.contains(header)) {
          if (module != null) {
            result.modules.add(module);
          }
          result.headers.add(header);
        }
      }
      for (int i = 0; i < transitiveHeaderInfo.textualHeaders.size(); i++) {
        Artifact header = transitiveHeaderInfo.textualHeaders.get(i);
        if (includes.contains(header)) {
          result.headers.add(header);
        }
      }
    }
    // Do not add the module of the current rule for both:
    // 1. the module compile itself
    // 2. compiles of other translation units of the same rule.
    result.modules.remove(headerInfo.getModule(usePic));
    return result;
  }

  private void removeArtifactsFromSet(Set<Artifact> set, Iterable<Artifact> artifacts) {
    // Do not use Iterables.removeAll() or Set.removeAll() here as with the given container sizes,
    // that needlessly deteriorates to a quadratic algorithm.
    for (Artifact artifact : artifacts) {
      set.remove(artifact);
    }
  }

  public NestedSet<Artifact> getTransitiveModules(boolean usePic) {
    return usePic ? transitivePicModules : transitiveModules;
  }

  /**
   * Returns the immutable set of additional transitive inputs needed for compilation, like C++
   * module map artifacts.
   */
  public NestedSet<Artifact> getAdditionalInputs() {
    NestedSetBuilder<Artifact> builder = NestedSetBuilder.stableOrder();
    addAdditionalInputs(builder);
    return builder.build();
  }

  /** Adds additional transitive inputs needed for compilation to builder. */
  void addAdditionalInputs(NestedSetBuilder<Artifact> builder) {
    builder.addAll(directModuleMaps);
    builder.addTransitive(nonCodeInputs);
    if (cppModuleMap != null && propagateModuleMapAsActionInput) {
      builder.add(cppModuleMap.getArtifact());
    }
  }

  /** @return modules maps from direct dependencies. */
  public Iterable<Artifact> getDirectModuleMaps() {
    return directModuleMaps;
  }

  /**
   * @return all declared headers of the current module if the current target
   * is compiled as a module.
   */
  protected Set<Artifact> getHeaderModuleSrcs() {
    return new ImmutableSet.Builder<Artifact>()
        .addAll(headerInfo.modularHeaders)
        .addAll(headerInfo.textualHeaders)
        .build();
  }

  /**
   * Returns the set of defines needed to compile this target. This includes definitions from the
   * transitive deps closure for the target. The order of the returned collection is deterministic.
   */
  public NestedSet<String> getDefines() {
    return commandLineCcCompilationContext.defines;
  }

  /**
   * Returns the set of defines needed to compile this target. This doesn't include definitions from
   * the transitive deps closure for the target.
   */
  ImmutableList<String> getNonTransitiveDefines() {
    return commandLineCcCompilationContext.localDefines;
  }

  /**
   * Returns a {@code CcCompilationContext} that is based on a given {@code CcCompilationContext}
   * but returns empty sets for {@link #getLooseHdrsDirs()}.
   */
  public static CcCompilationContext disallowUndeclaredHeaders(
      CcCompilationContext ccCompilationContext) {
    return new CcCompilationContext(
        ccCompilationContext.commandLineCcCompilationContext,
        ccCompilationContext.compilationPrerequisites,
        NestedSetBuilder.emptySet(Order.STABLE_ORDER),
        ccCompilationContext.declaredIncludeSrcs,
        ccCompilationContext.nonCodeInputs,
        ccCompilationContext.headerInfo,
        ccCompilationContext.transitiveHeaderInfos,
        ccCompilationContext.transitiveModules,
        ccCompilationContext.transitivePicModules,
        ccCompilationContext.directModuleMaps,
        ccCompilationContext.exportingModuleMaps,
        ccCompilationContext.cppModuleMap,
        ccCompilationContext.verificationModuleMap,
        ccCompilationContext.propagateModuleMapAsActionInput,
        ccCompilationContext.headersCheckingMode,
        ccCompilationContext.virtualToOriginalHeaders);
  }

  /** @return the C++ module map of the owner. */
  public CppModuleMap getCppModuleMap() {
    return cppModuleMap;
  }

  /** @return the C++ module map of the owner. */
  public CppModuleMap getVerificationModuleMap() {
    return verificationModuleMap;
  }

  /** Returns the list of dependencies' C++ module maps re-exported by this compilation context. */
  public ImmutableList<CppModuleMap> getExportingModuleMaps() {
    return exportingModuleMaps;
  }

  public CppConfiguration.HeadersCheckingMode getHeadersCheckingMode() {
    return headersCheckingMode;
  }

  public static ImmutableList<CcCompilationContext> getCcCompilationContexts(
      Iterable<? extends TransitiveInfoCollection> deps) {
    ImmutableList.Builder<CcCompilationContext> ccCompilationContextsBuilder =
        ImmutableList.builder();
    for (CcInfo ccInfo : AnalysisUtils.getProviders(deps, CcInfo.PROVIDER)) {
      ccCompilationContextsBuilder.add(ccInfo.getCcCompilationContext());
    }
    return ccCompilationContextsBuilder.build();
  }

  public static CcCompilationContext merge(Collection<CcCompilationContext> ccCompilationContexts) {
    CcCompilationContext.Builder builder =
        CcCompilationContext.builder(
            /* actionConstructionContext= */ null, /* configuration= */ null, /* label= */ null);
    builder.mergeDependentCcCompilationContexts(ccCompilationContexts);
    return builder.build();
  }

  public NestedSet<Pair<String, String>> getVirtualToOriginalHeaders() {
    return virtualToOriginalHeaders;
  }

  /**
   * The parts of the {@code CcCompilationContext} that influence the command line of compilation
   * actions.
   */
  @Immutable
  @AutoCodec
  @VisibleForSerialization
  static class CommandLineCcCompilationContext {
    private final ImmutableList<PathFragment> includeDirs;
    private final ImmutableList<PathFragment> quoteIncludeDirs;
    private final ImmutableList<PathFragment> systemIncludeDirs;
    private final ImmutableList<PathFragment> frameworkIncludeDirs;
    private final NestedSet<String> defines;
    private final ImmutableList<String> localDefines;

    CommandLineCcCompilationContext(
        ImmutableList<PathFragment> includeDirs,
        ImmutableList<PathFragment> quoteIncludeDirs,
        ImmutableList<PathFragment> systemIncludeDirs,
        ImmutableList<PathFragment> frameworkIncludeDirs,
        NestedSet<String> defines,
        ImmutableList<String> localDefines) {
      this.includeDirs = includeDirs;
      this.quoteIncludeDirs = quoteIncludeDirs;
      this.systemIncludeDirs = systemIncludeDirs;
      this.frameworkIncludeDirs = frameworkIncludeDirs;
      this.defines = defines;
      this.localDefines = localDefines;
    }
  }

  /** Creates a new builder for a {@link CcCompilationContext} instance. */
  public static Builder builder(
      ActionConstructionContext actionConstructionContext,
      BuildConfiguration configuration,
      Label label) {
    return new Builder(actionConstructionContext, configuration, label);
  }

  /** Builder class for {@link CcCompilationContext}. */
  public static class Builder {
    private String purpose;
    private final NestedSetBuilder<Artifact> compilationPrerequisites =
        NestedSetBuilder.stableOrder();
    private final Set<PathFragment> includeDirs = new LinkedHashSet<>();
    private final Set<PathFragment> quoteIncludeDirs = new LinkedHashSet<>();
    private final Set<PathFragment> systemIncludeDirs = new LinkedHashSet<>();
    private final Set<PathFragment> frameworkIncludeDirs = new LinkedHashSet<>();
    private final NestedSetBuilder<PathFragment> looseHdrsDirs = NestedSetBuilder.stableOrder();
    private final NestedSetBuilder<Artifact> declaredIncludeSrcs =
        NestedSetBuilder.stableOrder();
    private final NestedSetBuilder<Artifact> nonCodeInputs = NestedSetBuilder.stableOrder();
    private final HeaderInfo.Builder headerInfoBuilder = new HeaderInfo.Builder();
    private final NestedSetBuilder<HeaderInfo> transitiveHeaderInfo =
        NestedSetBuilder.stableOrder();
    private final NestedSetBuilder<Artifact> transitiveModules = NestedSetBuilder.stableOrder();
    private final NestedSetBuilder<Artifact> transitivePicModules = NestedSetBuilder.stableOrder();
    private final Set<Artifact> directModuleMaps = new LinkedHashSet<>();
    private final Set<CppModuleMap> exportingModuleMaps = new LinkedHashSet<>();
    private final NestedSetBuilder<String> defines = NestedSetBuilder.linkOrder();
    private final Set<String> localDefines = new LinkedHashSet<>();
    private CppModuleMap cppModuleMap;
    private CppModuleMap verificationModuleMap;
    private boolean propagateModuleMapAsActionInput = true;
    private CppConfiguration.HeadersCheckingMode headersCheckingMode =
        CppConfiguration.HeadersCheckingMode.STRICT;
    private NestedSetBuilder<Pair<String, String>> virtualToOriginalHeaders =
        NestedSetBuilder.stableOrder();

    /** The rule that owns the context */
    private final ActionConstructionContext actionConstructionContext;

    private final BuildConfiguration configuration;
    private final Label label;

    /** Creates a new builder for a {@link CcCompilationContext} instance. */
    private Builder(
        ActionConstructionContext actionConstructionContext,
        BuildConfiguration configuration,
        Label label) {
      this.actionConstructionContext = actionConstructionContext;
      this.configuration = configuration;
      this.label = label;
    }

    /**
     * Overrides the purpose of this context. This is useful if a Target needs more than one
     * CcCompilationContext. (The purpose is used to construct the name of the prerequisites
     * middleman for the context, and all artifacts for a given Target must have distinct names.)
     *
     * @param purpose must be a string which is suitable for use as a filename. A single rule may
     *     have many middlemen with distinct purposes.
     * @see MiddlemanFactory#createSchedulingDependencyMiddleman
     */
    public Builder setPurpose(String purpose) {
      this.purpose = purpose;
      return this;
    }

    public String getPurpose() {
      return purpose;
    }

    /**
     * Merges the {@link CcCompilationContext} of a dependency into this one by adding the contents
     * of all of its attributes.
     */
    public Builder mergeDependentCcCompilationContext(
        CcCompilationContext otherCcCompilationContext) {
      Preconditions.checkNotNull(otherCcCompilationContext);
      compilationPrerequisites.addTransitive(
          otherCcCompilationContext.getTransitiveCompilationPrerequisites());
      includeDirs.addAll(otherCcCompilationContext.getIncludeDirs());
      quoteIncludeDirs.addAll(otherCcCompilationContext.getQuoteIncludeDirs());
      systemIncludeDirs.addAll(otherCcCompilationContext.getSystemIncludeDirs());
      frameworkIncludeDirs.addAll(otherCcCompilationContext.getFrameworkIncludeDirs());
      looseHdrsDirs.addTransitive(otherCcCompilationContext.getLooseHdrsDirs());
      declaredIncludeSrcs.addTransitive(otherCcCompilationContext.getDeclaredIncludeSrcs());
      transitiveHeaderInfo.addTransitive(otherCcCompilationContext.transitiveHeaderInfos);
      transitiveModules.addTransitive(otherCcCompilationContext.transitiveModules);
      if (otherCcCompilationContext.headerInfo.headerModule != null) {
        transitiveModules.add(otherCcCompilationContext.headerInfo.headerModule);
      }
      transitivePicModules.addTransitive(otherCcCompilationContext.transitivePicModules);
      if (otherCcCompilationContext.headerInfo.picHeaderModule != null) {
        transitivePicModules.add(otherCcCompilationContext.headerInfo.picHeaderModule);
      }

      nonCodeInputs.addTransitive(otherCcCompilationContext.nonCodeInputs);

      // All module maps of direct dependencies are inputs to the current compile independently of
      // the build type.
      if (otherCcCompilationContext.getCppModuleMap() != null) {
        directModuleMaps.add(otherCcCompilationContext.getCppModuleMap().getArtifact());
      }
      // Likewise, module maps re-exported from dependencies are inputs to the current compile.
      for (CppModuleMap moduleMap : otherCcCompilationContext.exportingModuleMaps) {
        directModuleMaps.add(moduleMap.getArtifact());
      }

      defines.addTransitive(otherCcCompilationContext.getDefines());
      virtualToOriginalHeaders.addTransitive(
          otherCcCompilationContext.getVirtualToOriginalHeaders());
      return this;
    }

    /**
     * Merges the given {@code CcCompilationContext}s into this one by adding the contents of their
     * attributes.
     */
    public Builder mergeDependentCcCompilationContexts(
        Iterable<CcCompilationContext> ccCompilationContexts) {
      for (CcCompilationContext ccCompilationContext : ccCompilationContexts) {
        mergeDependentCcCompilationContext(ccCompilationContext);
      }
      return this;
    }

    /**
     * Merges the given {@code CcCompilationContext}s into this one by adding the contents of their
     * attributes, and re-exporting the direct headers and module maps of {@code
     * exportedCcCompilationContexts} through this one.
     */
    public Builder mergeDependentCcCompilationContexts(
        Iterable<CcCompilationContext> exportedCcCompilationContexts,
        Iterable<CcCompilationContext> ccCompilationContexts) {
      for (CcCompilationContext ccCompilationContext :
          Iterables.concat(exportedCcCompilationContexts, ccCompilationContexts)) {
        mergeDependentCcCompilationContext(ccCompilationContext);
      }

      for (CcCompilationContext ccCompilationContext : exportedCcCompilationContexts) {
        // For each of the exported contexts, re-export its own module map and all of the module
        // maps that it exports.
        CppModuleMap moduleMap = ccCompilationContext.getCppModuleMap();
        if (moduleMap != null) {
          exportingModuleMaps.add(moduleMap);
        }
        exportingModuleMaps.addAll(ccCompilationContext.exportingModuleMaps);

        // Merge the modular and textual headers from the compilation context so that they are also
        // re-exported.
        headerInfoBuilder.mergeHeaderInfo(ccCompilationContext.headerInfo);
      }

      return this;
    }

    /**
     * Add a single include directory to be added with "-I". It can be either relative to the exec
     * root (see {@link
     * com.google.devtools.build.lib.analysis.BlazeDirectories#getExecRoot(String)}) or absolute.
     * Before it is stored, the include directory is normalized.
     */
    public Builder addIncludeDir(PathFragment includeDir) {
      includeDirs.add(includeDir);
      return this;
    }

    /** See {@link #addIncludeDir(PathFragment)} */
    public Builder addIncludeDirs(Iterable<PathFragment> includeDirs) {
      Iterables.addAll(this.includeDirs, includeDirs);
      return this;
    }

    /**
     * Add a single include directory to be added with "-iquote". It can be either relative to the
     * exec root (see {@link
     * com.google.devtools.build.lib.analysis.BlazeDirectories#getExecRoot(String)}) or absolute.
     * Before it is stored, the include directory is normalized.
     */
    public Builder addQuoteIncludeDir(PathFragment quoteIncludeDir) {
      quoteIncludeDirs.add(quoteIncludeDir);
      return this;
    }

    /** See {@link #addQuoteIncludeDir(PathFragment)} */
    public Builder addQuoteIncludeDirs(Iterable<PathFragment> quoteIncludeDirs) {
      Iterables.addAll(this.quoteIncludeDirs, quoteIncludeDirs);
      return this;
    }

    /**
     * Add include directories to be added with "-isystem". It can be either relative to the exec
     * root (see {@link
     * com.google.devtools.build.lib.analysis.BlazeDirectories#getExecRoot(String)}) or absolute.
     * Before it is stored, the include directory is normalized.
     */
    public Builder addSystemIncludeDirs(Iterable<PathFragment> systemIncludeDirs) {
      Iterables.addAll(this.systemIncludeDirs, systemIncludeDirs);
      return this;
    }

    /** Add framewrok include directories to be added with "-F". */
    public Builder addFrameworkIncludeDirs(Iterable<PathFragment> frameworkIncludeDirs) {
      Iterables.addAll(this.frameworkIncludeDirs, frameworkIncludeDirs);
      return this;
    }

    /** Add a single declared include dir, relative to a "-I" or "-iquote" directory". */
    public Builder addLooseHdrsDir(PathFragment dir) {
      looseHdrsDirs.add(dir);
      return this;
    }

    /**
     * Adds a header that has been declared in the {@code src} or {@code headers attribute}. The
     * header will also be added to the compilation prerequisites.
     *
     * <p>Filters out fileset directory artifacts, which are not valid inputs.
     */
    public Builder addDeclaredIncludeSrc(Artifact header) {
      if (!header.isFileset()) {
        declaredIncludeSrcs.add(header);
        compilationPrerequisites.add(header);
      }
      return this;
    }

    /**
     * Adds multiple headers that have been declared in the {@code src} or {@code headers
     * attribute}. The headers will also be added to the compilation prerequisites.
     *
     * <p>Filters out fileset directory artifacts, which are not valid inputs.
     */
    public Builder addDeclaredIncludeSrcs(Iterable<Artifact> declaredIncludeSrcs) {
      for (Artifact source : declaredIncludeSrcs) {
        addDeclaredIncludeSrc(source);
      }
      return this;
    }

    public Builder addModularHdrs(Collection<Artifact> headers) {
      this.headerInfoBuilder.addHeaders(headers);
      return this;
    }

    public Builder addTextualHdrs(Collection<Artifact> headers) {
      this.headerInfoBuilder.addTextualHeaders(headers);
      return this;
    }

    /** Add a set of required non-code compilation input. */
    public Builder addNonCodeInputs(Iterable<Artifact> inputs) {
      nonCodeInputs.addAll(inputs);
      return this;
    }

    /** Adds a single define. */
    public Builder addDefine(String define) {
      defines.add(define);
      return this;
    }

    /** Adds multiple defines. */
    public Builder addDefines(NestedSet<String> defines) {
      this.defines.addTransitive(defines);
      return this;
    }

    /** Adds multiple non-transitive defines. */
    public Builder addNonTransitiveDefines(Iterable<String> defines) {
      Iterables.addAll(this.localDefines, defines);
      return this;
    }

    /** Sets the C++ module map. */
    public Builder setCppModuleMap(CppModuleMap cppModuleMap) {
      this.cppModuleMap = cppModuleMap;
      return this;
    }

    /** Sets the C++ module map used to verify that headers are modules compatible. */
    public Builder setVerificationModuleMap(CppModuleMap verificationModuleMap) {
      this.verificationModuleMap = verificationModuleMap;
      return this;
    }

    /**
     * Causes the module map to be passed as an action input to dependant compilations.
     */
    public Builder setPropagateCppModuleMapAsActionInput(boolean propagateModuleMap) {
      this.propagateModuleMapAsActionInput = propagateModuleMap;
      return this;
    }

    /**
     * Sets the C++ header module in non-pic mode.
     *
     * @param headerModule The .pcm file generated for this library.
     */
    Builder setHeaderModule(Artifact.DerivedArtifact headerModule) {
      this.headerInfoBuilder.setHeaderModule(headerModule);
      return this;
    }

    /**
     * Sets the C++ header module in pic mode.
     *
     * @param picHeaderModule The .pic.pcm file generated for this library.
     */
    Builder setPicHeaderModule(Artifact.DerivedArtifact picHeaderModule) {
      this.headerInfoBuilder.setPicHeaderModule(picHeaderModule);
      return this;
    }

    public Builder setHeadersCheckingMode(
        CppConfiguration.HeadersCheckingMode headersCheckingMode) {
      this.headersCheckingMode = headersCheckingMode;
      return this;
    }

    public Builder addVirtualToOriginalHeaders(
        NestedSet<Pair<String, String>> virtualToOriginalHeaders) {
      this.virtualToOriginalHeaders.addTransitive(virtualToOriginalHeaders);
      return this;
    }

    /** Builds the {@link CcCompilationContext}. */
    public CcCompilationContext build() {
      return build(
          actionConstructionContext == null ? null : actionConstructionContext.getActionOwner(),
          actionConstructionContext == null
              ? null
              : actionConstructionContext.getAnalysisEnvironment().getMiddlemanFactory());
    }

    @VisibleForTesting // productionVisibility = Visibility.PRIVATE
    public CcCompilationContext build(ActionOwner owner, MiddlemanFactory middlemanFactory) {
      NestedSet<Artifact> constructedPrereq = createMiddleman(owner, middlemanFactory);
      HeaderInfo headerInfo = headerInfoBuilder.build();
      transitiveHeaderInfo.add(headerInfo);

      return new CcCompilationContext(
          new CommandLineCcCompilationContext(
              ImmutableList.copyOf(includeDirs),
              ImmutableList.copyOf(quoteIncludeDirs),
              ImmutableList.copyOf(systemIncludeDirs),
              ImmutableList.copyOf(frameworkIncludeDirs),
              defines.build(),
              ImmutableList.copyOf(localDefines)),
          constructedPrereq,
          looseHdrsDirs.build(),
          declaredIncludeSrcs.build(),
          nonCodeInputs.build(),
          headerInfo,
          transitiveHeaderInfo.build(),
          transitiveModules.build(),
          transitivePicModules.build(),
          ImmutableList.copyOf(directModuleMaps),
          ImmutableList.copyOf(exportingModuleMaps),
          cppModuleMap,
          verificationModuleMap,
          propagateModuleMapAsActionInput,
          headersCheckingMode,
          virtualToOriginalHeaders.build());
    }

    /** Creates a middleman for the compilation prerequisites. */
    private NestedSet<Artifact> createMiddleman(
        ActionOwner owner, MiddlemanFactory middlemanFactory) {
      if (middlemanFactory == null) {
        // TODO(b/110873917): We don't have a middleman factory, therefore, we use the compilation
        // prerequisites as they were passed to the builder, i.e. we use every header instead of a
        // middle man.
        return compilationPrerequisites.build();
      }
      if (compilationPrerequisites.isEmpty()) {
        return compilationPrerequisites.build();
      }

      // Compilation prerequisites gathered in the compilationPrerequisites must be generated prior
      // to executing a C++ compilation step that depends on them (since these prerequisites include
      // all potential header files, etc that could be referenced during compilation). So there is a
      // definite need to ensure a scheduling dependency. However, those prerequisites should have
      // no effect on the decision whether C++ compilation should happen in the first place - only
      // the CppCompileAction outputs (.o and .d files) and all files referenced by the .d file
      // should be used to make that decision.
      //
      // If this action was never executed, then the .d file is missing, forcing compilation. If the
      // .d file is present and has not changed then the only reason that would force us to
      // re-compile would be change in one of the files referenced by the .d file, since no other
      // files participated in the compilation.
      //
      // We also need to propagate errors through this dependency link. Therefore, we use a
      // scheduling dependency middleman. Such a middleman will be ignored by the dependency checker
      // yet still represents an edge in the action dependency graph - forcing proper execution
      // order and error propagation.
      String name = cppModuleMap != null ? cppModuleMap.getName() : label.toString();
      Artifact prerequisiteStampFile =
          middlemanFactory.createSchedulingDependencyMiddleman(
              owner,
              name,
              purpose,
              compilationPrerequisites.build(),
              configuration.getMiddlemanDirectory(label.getPackageIdentifier().getRepository()));
      return NestedSetBuilder.create(Order.STABLE_ORDER, prerequisiteStampFile);
    }
  }

  /**
   * Gathers data about the PIC and no-PIC .pcm files belonging to this context and the associated
   * information about the headers, e.g. modular vs. textual headers and pre-grepped header files.
   */
  @Immutable
  @AutoCodec
  public static final class HeaderInfo {
    /**
     * The modules built for this context. If null, then no module is being compiled for this
     * context.
     */
    private final Artifact.DerivedArtifact headerModule;

    private final Artifact.DerivedArtifact picHeaderModule;

    /** All header files that are compiled into this module. */
    private final ImmutableList<Artifact> modularHeaders;

    /** All header files that are contained in this module. */
    private final ImmutableList<Artifact> textualHeaders;

    HeaderInfo(
        Artifact.DerivedArtifact headerModule,
        Artifact.DerivedArtifact picHeaderModule,
        ImmutableList<Artifact> modularHeaders,
        ImmutableList<Artifact> textualHeaders) {
      this.headerModule = headerModule;
      this.picHeaderModule = picHeaderModule;
      this.modularHeaders = modularHeaders;
      this.textualHeaders = textualHeaders;
    }

    Artifact.DerivedArtifact getModule(boolean pic) {
      return pic ? picHeaderModule : headerModule;
    }

    /**
     * Builder class for {@link HeaderInfo}.
     */
    public static class Builder {
      private Artifact.DerivedArtifact headerModule = null;
      private Artifact.DerivedArtifact picHeaderModule = null;
      private final Set<Artifact> modularHeaders = new HashSet<>();
      private final Set<Artifact> textualHeaders = new HashSet<>();

      Builder setHeaderModule(Artifact.DerivedArtifact headerModule) {
        this.headerModule = headerModule;
        return this;
      }

      Builder setPicHeaderModule(Artifact.DerivedArtifact headerModule) {
        this.picHeaderModule = headerModule;
        return this;
      }

      public Builder addHeaders(Collection<Artifact> headers) {
        // TODO(djasper): CPP_TEXTUAL_INCLUDEs are currently special cased here and in
        // CppModuleMapAction. These should be moved to a place earlier in the Action construction.
        for (Artifact header : headers) {
          if (header.isFileType(CppFileTypes.CPP_TEXTUAL_INCLUDE)) {
            this.textualHeaders.add(header);
          } else {
            this.modularHeaders.add(header);
          }
        }
        return this;
      }

      public Builder addTextualHeaders(Collection<Artifact> headers) {
        this.textualHeaders.addAll(headers);
        return this;
      }

      /** Adds the headers of the given {@code HeaderInfo} into the one being built. */
      public Builder mergeHeaderInfo(HeaderInfo otherHeaderInfo) {
        this.modularHeaders.addAll(otherHeaderInfo.modularHeaders);
        this.textualHeaders.addAll(otherHeaderInfo.textualHeaders);
        return this;
      }

      public HeaderInfo build() {
        return new HeaderInfo(
            headerModule,
            picHeaderModule,
            ImmutableList.copyOf(modularHeaders),
            ImmutableList.copyOf(textualHeaders));
      }
    }
  }
}
