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

import static com.google.common.base.MoreObjects.firstNonNull;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.collect.BiMap;
import com.google.common.collect.ImmutableList;
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.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.devtools.build.lib.bugreport.BugReport;
import com.google.devtools.build.lib.cmdline.BazelModuleContext;
import com.google.devtools.build.lib.cmdline.BazelModuleContext.LoadGraphVisitor;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.cmdline.LabelConstants;
import com.google.devtools.build.lib.cmdline.LabelSyntaxException;
import com.google.devtools.build.lib.cmdline.PackageIdentifier;
import com.google.devtools.build.lib.cmdline.RepositoryMapping;
import com.google.devtools.build.lib.cmdline.RepositoryName;
import com.google.devtools.build.lib.cmdline.TargetPattern;
import com.google.devtools.build.lib.collect.CollectionUtils;
import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadCompatible;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.events.EventHandler;
import com.google.devtools.build.lib.events.EventKind;
import com.google.devtools.build.lib.events.ExtendedEventHandler;
import com.google.devtools.build.lib.events.ExtendedEventHandler.Postable;
import com.google.devtools.build.lib.events.StoredEventHandler;
import com.google.devtools.build.lib.packages.Package.Builder.PackageSettings;
import com.google.devtools.build.lib.server.FailureDetails.FailureDetail;
import com.google.devtools.build.lib.server.FailureDetails.PackageLoading;
import com.google.devtools.build.lib.server.FailureDetails.PackageLoading.Code;
import com.google.devtools.build.lib.skyframe.serialization.DeserializationContext;
import com.google.devtools.build.lib.skyframe.serialization.ObjectCodec;
import com.google.devtools.build.lib.skyframe.serialization.SerializationContext;
import com.google.devtools.build.lib.skyframe.serialization.SerializationException;
import com.google.devtools.build.lib.util.DetailedExitCode;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.PathFragment;
import com.google.devtools.build.lib.vfs.Root;
import com.google.devtools.build.lib.vfs.RootedPath;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import com.google.protobuf.CodedInputStream;
import com.google.protobuf.CodedOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.OptionalInt;
import java.util.OptionalLong;
import java.util.Set;
import java.util.TreeMap;
import java.util.concurrent.Semaphore;
import javax.annotation.Nullable;
import net.starlark.java.eval.Module;
import net.starlark.java.eval.StarlarkThread;
import net.starlark.java.syntax.Location;

/**
 * A package, which is a container of {@link Rule}s, each of which contains a dictionary of named
 * attributes.
 *
 * <p>Package instances are intended to be immutable and for all practical purposes can be treated
 * as such. Note, however, that some member variables exposed via the public interface are not
 * strictly immutable, so until their types are guaranteed immutable we're not applying the
 * {@code @Immutable} annotation here.
 *
 * <p>This class should not be extended - it's only non-final for mocking!
 *
 * <p>When changing this class, make sure to make corresponding changes to serialization!
 */
@SuppressWarnings("JavaLangClash")
public class Package {

  private final Metadata metadata;

  /**
   * The "workspace name" of packages generated by Bzlmod to contain repo rules.
   *
   * <p>Normally, packages containing repo rules are differentiated from packages containing build
   * rules by the {@link PackageIdentifier}: The singular repo-rule-containing package is {@code
   * //external}. However, in Bzlmod, packages containing repo rules need to have meaningful {@link
   * PackageIdentifier}s, so there needs to be some other way to distinguish them from
   * build-rule-containing packages. We use the following magic string as the "workspace name" for
   * repo-rule-containing packages generated by Bzlmod.
   *
   * @see #isRepoRulePackage()
   */
  private static final String DUMMY_WORKSPACE_NAME_FOR_BZLMOD_PACKAGES = "__dummy_workspace_bzlmod";

  /** Sentinel value for package overhead being empty. */
  private static final long PACKAGE_OVERHEAD_UNSET = -1;

  /** Common superclass for all name-conflict exceptions. */
  public static class NameConflictException extends Exception {
    private NameConflictException(String message) {
      super(message);
    }
  }

  /** The collection of all targets defined in this package, indexed by name. */
  private ImmutableSortedMap<String, Target> targets;

  public PackageArgs getPackageArgs() {
    return metadata.packageArgs;
  }

  /**
   * How to enforce config_setting visibility settings.
   *
   * <p>This is a temporary setting in service of https://github.com/bazelbuild/bazel/issues/12669.
   * After enough depot cleanup, config_setting will have the same visibility enforcement as all
   * other rules.
   */
  public enum ConfigSettingVisibilityPolicy {
    /** Don't enforce visibility for any config_setting. */
    LEGACY_OFF,
    /** Honor explicit visibility settings on config_setting, else use //visibility:public. */
    DEFAULT_PUBLIC,
    /** Enforce config_setting visibility exactly the same as all other rules. */
    DEFAULT_STANDARD
  }

  /**
   * True iff this package's BUILD files contained lexical or grammatical errors, or experienced
   * errors during evaluation, or semantic errors during the construction of any rule.
   *
   * <p>Note: A package containing errors does not necessarily prevent a build; if all the rules
   * needed for a given build were constructed prior to the first error, the build may proceed.
   */
  private boolean containsErrors;

  /**
   * The first detailed error encountered during this package's construction and evaluation, or
   * {@code null} if there were no such errors or all its errors lacked details.
   */
  @Nullable private FailureDetail failureDetail;

  /**
   * The map from each repository to that repository's remappings map. This is only used in the
   * //external package, it is an empty map for all other packages. For example, an entry of {"@foo"
   * : {"@x", "@y"}} indicates that, within repository foo, "@x" should be remapped to "@y".
   */
  private ImmutableMap<RepositoryName, ImmutableMap<String, RepositoryName>>
      externalPackageRepositoryMappings;

  /**
   * A rough approximation of the memory and general accounting costs associated with a loaded
   * package. A value of -1 means it is unset. Stored as a long to take up less memory per pkg.
   */
  private long packageOverhead = PACKAGE_OVERHEAD_UNSET;

  /** Returns package overhead as configured by the configured {@link PackageOverheadEstimator}. */
  public OptionalLong getPackageOverhead() {
    return packageOverhead == PACKAGE_OVERHEAD_UNSET
        ? OptionalLong.empty()
        : OptionalLong.of(packageOverhead);
  }

  /** Sets package overhead as configured by the configured {@link PackageOverheadEstimator}. */
  void setPackageOverhead(OptionalLong packageOverhead) {
    this.packageOverhead =
        packageOverhead.isPresent() ? packageOverhead.getAsLong() : PACKAGE_OVERHEAD_UNSET;
  }

  private ImmutableList<TargetPattern> registeredExecutionPlatforms;
  private ImmutableList<TargetPattern> registeredToolchains;
  private OptionalInt firstWorkspaceSuffixRegisteredToolchain;
  private long computationSteps;

  /** Returns the number of Starlark computation steps executed by this BUILD file. */
  public long getComputationSteps() {
    return computationSteps;
  }

  /**
   * Constructs a new (incomplete) Package instance. Intended only for use by {@link
   * Package.Builder}.
   *
   * <p>Packages and Targets refer to one another. Therefore, the builder needs to have a Package
   * instance on-hand before it can associate any targets with the package. Certain Metadata fields
   * like the package's name must be known before that point, while other fields are filled in when
   * the builder calls {@link Package#finishInit}.
   */
  // TODO(#19922): Better separate fields that must be known a priori from those determined through
  // BUILD evaluation.
  private Package(Metadata metadata) {
    this.metadata = metadata;
  }

  /** Returns this package's identifier. */
  public PackageIdentifier getPackageIdentifier() {
    return metadata.packageIdentifier;
  }

  /**
   * Whether this package should contain only repo rules (returns {@code true}) or only build rules
   * (returns {@code false}).
   */
  private boolean isRepoRulePackage() {
    return metadata.packageIdentifier.equals(LabelConstants.EXTERNAL_PACKAGE_IDENTIFIER)
        || metadata.workspaceName.equals(DUMMY_WORKSPACE_NAME_FOR_BZLMOD_PACKAGES);
  }

  /**
   * Returns the repository mapping for the requested external repository.
   *
   * @throws UnsupportedOperationException if called from a package other than the //external
   *     package
   */
  public ImmutableMap<String, RepositoryName> getRepositoryMapping(RepositoryName repository) {
    if (!isRepoRulePackage()) {
      throw new UnsupportedOperationException(
          "Can only access the external package repository"
              + "mappings from the //external package");
    }
    return externalPackageRepositoryMappings.getOrDefault(repository, ImmutableMap.of());
  }

  /** Get the repository mapping for this package. */
  public RepositoryMapping getRepositoryMapping() {
    return metadata.repositoryMapping;
  }

  /**
   * Returns the full map of repository mappings collected so far.
   *
   * @throws UnsupportedOperationException if called from a package other than the //external
   *     package
   */
  ImmutableMap<RepositoryName, ImmutableMap<String, RepositoryName>>
      getExternalPackageRepositoryMappings() {
    if (!isRepoRulePackage()) {
      throw new UnsupportedOperationException(
          "Can only access the external package repository"
              + "mappings from the //external package");
    }
    return this.externalPackageRepositoryMappings;
  }

  /**
   * Returns the source root (a directory) beneath which this package's BUILD file was found, or
   * {@link Optional#empty} if this package was derived from a workspace file.
   *
   * <p>Assumes invariant: If non-empty, {@code
   * getSourceRoot().get().getRelative(packageId.getSourceRoot()).equals(getPackageDirectory())}
   */
  public Optional<Root> getSourceRoot() {
    return metadata.sourceRoot;
  }

  private static Root getSourceRoot(RootedPath buildFileRootedPath, PathFragment packageFragment) {
    PathFragment packageDirectory = buildFileRootedPath.getRootRelativePath().getParentDirectory();
    if (packageFragment.equals(packageDirectory)) {
      // Fast path: BUILD file path and package name are the same, don't create an extra root.
      return buildFileRootedPath.getRoot();
    }
    PathFragment current = buildFileRootedPath.asPath().asFragment().getParentDirectory();
    for (int i = 0, len = packageFragment.segmentCount(); i < len && current != null; i++) {
      current = current.getParentDirectory();
    }
    if (current == null || current.isEmpty()) {
      // This is never really expected to work. The check below in #finishInit should fail.
      return buildFileRootedPath.getRoot();
    }
    // Note that current is an absolute path.
    return Root.fromPath(buildFileRootedPath.getRoot().getRelative(current));
  }

  /**
   * Completes the initialization of this package. Only after this method may a package by shared
   * publicly.
   */
  private void finishInit(Builder builder) {
    String baseName = metadata.filename.getRootRelativePath().getBaseName();

    this.containsErrors |= builder.containsErrors;
    if (metadata.directLoads == null && metadata.transitiveLoads == null) {
      Preconditions.checkState(containsErrors, "Loads not set for error-free package");
      builder.setLoads(ImmutableList.of());
    }

    if (isWorkspaceFile(baseName) || isModuleDotBazelFile(baseName)) {
      Preconditions.checkState(isRepoRulePackage());
      this.metadata.sourceRoot = Optional.empty();
    } else {
      Root sourceRoot =
          getSourceRoot(metadata.filename, metadata.packageIdentifier.getSourceRoot());
      if (sourceRoot.asPath() == null
          || !sourceRoot
              .getRelative(metadata.packageIdentifier.getSourceRoot())
              .equals(metadata.packageDirectory)) {
        throw new IllegalArgumentException(
            "Invalid BUILD file name for package '"
                + metadata.packageIdentifier
                + "': "
                + metadata.filename
                + " (in source "
                + sourceRoot
                + " with packageDirectory "
                + metadata.packageDirectory
                + " and package identifier source root "
                + metadata.packageIdentifier.getSourceRoot()
                + ")");
      }
      this.metadata.sourceRoot = Optional.of(sourceRoot);
    }

    this.metadata.makeEnv = ImmutableMap.copyOf(builder.makeEnv);
    this.targets = ImmutableSortedMap.copyOf(builder.targets);
    this.failureDetail = builder.getFailureDetail();
    this.registeredExecutionPlatforms = ImmutableList.copyOf(builder.registeredExecutionPlatforms);
    this.registeredToolchains = ImmutableList.copyOf(builder.registeredToolchains);
    this.firstWorkspaceSuffixRegisteredToolchain = builder.firstWorkspaceSuffixRegisteredToolchain;
    ImmutableMap.Builder<RepositoryName, ImmutableMap<String, RepositoryName>>
        repositoryMappingsBuilder = ImmutableMap.builder();
    if (!builder.externalPackageRepositoryMappings.isEmpty() && !builder.isRepoRulePackage()) {
      // 'repo_mapping' should only be used in the //external package, i.e. should only appear
      // in WORKSPACE files. Currently, if someone tries to use 'repo_mapping' in a BUILD rule, they
      // will get a "no such attribute" error. This check is to protect against a 'repo_mapping'
      // attribute being added to a rule in the future.
      throw new IllegalArgumentException(
          "'repo_mapping' may only be used in the //external package");
    }
    builder.externalPackageRepositoryMappings.forEach(
        (k, v) -> repositoryMappingsBuilder.put(k, ImmutableMap.copyOf(v)));
    this.externalPackageRepositoryMappings = repositoryMappingsBuilder.buildOrThrow();
    setPackageOverhead(builder.packageOverheadEstimator.estimatePackageOverhead(this));
  }

  private static boolean isWorkspaceFile(String baseFileName) {
    return baseFileName.equals(LabelConstants.WORKSPACE_DOT_BAZEL_FILE_NAME.getPathString())
        || baseFileName.equals(LabelConstants.WORKSPACE_FILE_NAME.getPathString());
  }

  private static boolean isModuleDotBazelFile(String baseFileName) {
    return baseFileName.equals(LabelConstants.MODULE_DOT_BAZEL_FILE_NAME.getPathString());
  }

  public Metadata getMetadata() {
    return metadata;
  }

  /**
   * Returns a list of Starlark files transitively loaded by this package.
   *
   * <p>If transitive loads are not {@linkplain PackageSettings#precomputeTransitiveLoads
   * precomputed}, performs a traversal over the load graph to compute them.
   *
   * <p>If only the count of transitively loaded files is needed, use {@link
   * #countTransitivelyLoadedStarlarkFiles}. For a customized online visitation, use {@link
   * #visitLoadGraph}.
   */
  public ImmutableList<Label> getOrComputeTransitivelyLoadedStarlarkFiles() {
    // TODO(bazel-team): Seems like a code smell that Metadata fields are being mutated here,
    // possibly after package construction is complete.
    return metadata.transitiveLoads != null
        ? metadata.transitiveLoads
        : computeTransitiveLoads(metadata.directLoads);
  }

  /**
   * Counts the number Starlark files transitively loaded by this package.
   *
   * <p>If transitive loads are not {@linkplain PackageSettings#precomputeTransitiveLoads
   * precomputed}, performs a traversal over the load graph to count them.
   */
  public int countTransitivelyLoadedStarlarkFiles() {
    if (metadata.transitiveLoads != null) {
      return metadata.transitiveLoads.size();
    }
    Set<Label> loads = new HashSet<>();
    visitLoadGraph(loads::add);
    return loads.size();
  }

  /**
   * Performs an online visitation of the load graph rooted at this package.
   *
   * <p>If transitive loads were {@linkplain PackageSettings#precomputeTransitiveLoads precomputed},
   * each file is passed to {@link LoadGraphVisitor#visit} once regardless of its return value.
   */
  public <E1 extends Exception, E2 extends Exception> void visitLoadGraph(
      LoadGraphVisitor<E1, E2> visitor) throws E1, E2 {
    if (metadata.transitiveLoads != null) {
      for (Label load : metadata.transitiveLoads) {
        visitor.visit(load);
      }
    } else {
      BazelModuleContext.visitLoadGraphRecursively(metadata.directLoads, visitor);
    }
  }

  private static ImmutableList<Label> computeTransitiveLoads(Iterable<Module> directLoads) {
    Set<Label> loads = new LinkedHashSet<>();
    BazelModuleContext.visitLoadGraphRecursively(directLoads, loads::add);
    return ImmutableList.copyOf(loads);
  }

  /**
   * Returns the filename of the BUILD file which defines this package. The parent directory of the
   * BUILD file is the package directory.
   */
  public RootedPath getFilename() {
    return metadata.filename;
  }

  /** Returns the directory containing the package's BUILD file. */
  public Path getPackageDirectory() {
    return metadata.packageDirectory;
  }

  /**
   * Returns the name of this package. If this build is using external repositories then this name
   * may not be unique!
   */
  public String getName() {
    return metadata.getName();
  }

  /** Like {@link #getName}, but has type {@code PathFragment}. */
  public PathFragment getNameFragment() {
    return metadata.getNameFragment();
  }

  /** Returns all make variables for a given platform. */
  public ImmutableMap<String, String> getMakeEnvironment() {
    return metadata.makeEnv;
  }

  /**
   * Returns the label of this package's BUILD file.
   *
   * <p>Typically <code>getBuildFileLabel().getName().equals("BUILD")</code> -- though not
   * necessarily: data in a subdirectory of a test package may use a different filename to avoid
   * inadvertently creating a new package.
   */
  public Label getBuildFileLabel() {
    return metadata.buildFile.getLabel();
  }

  /** Returns the InputFile target for this package's BUILD file. */
  public InputFile getBuildFile() {
    return metadata.buildFile;
  }

  /**
   * Returns true if errors were encountered during evaluation of this package. (The package may be
   * incomplete and its contents should not be relied upon for critical operations. However, any
   * Rules belonging to the package are guaranteed to be intact, unless their <code>containsErrors()
   * </code> flag is set.)
   */
  public boolean containsErrors() {
    return containsErrors;
  }

  /**
   * If {@code pkg.containsErrors()}, sends an errorful "package contains errors" {@link Event}
   * (augmented with {@code pkg.getFailureDetail()}, if present) to the given {@link EventHandler}.
   */
  public static void maybeAddPackageContainsErrorsEventToHandler(
      Package pkg, EventHandler eventHandler) {
    if (pkg.containsErrors()) {
      eventHandler.handle(
          Event.error(
              String.format(
                  "package contains errors: %s%s",
                  pkg.getNameFragment(),
                  pkg.getFailureDetail() != null
                      ? ": " + pkg.getFailureDetail().getMessage()
                      : "")));
    }
  }

  // TODO(bazel-team): Seems like we shouldn't permit this mutation on an already-initialized
  // Package. Is it possible for this to be called today after initialization?
  void setContainsErrors() {
    containsErrors = true;
  }

  /**
   * Returns the first {@link FailureDetail} describing one of the package's errors, or {@code null}
   * if it has no errors or all its errors lack details.
   */
  @Nullable
  public FailureDetail getFailureDetail() {
    return failureDetail;
  }

  /**
   * Returns a {@link FailureDetail} attributing a target error to the package's {@link
   * FailureDetail}, or a generic {@link Code#TARGET_MISSING} failure detail if the package has
   * none.
   *
   * <p>May only be called when {@link #containsErrors()} is true and with a target whose package is
   * this one.
   */
  public FailureDetail contextualizeFailureDetailForTarget(Target target) {
    Preconditions.checkState(
        target.getPackage().metadata.packageIdentifier.equals(metadata.packageIdentifier),
        "contextualizeFailureDetailForTarget called for target not in package. target=%s,"
            + " package=%s",
        target,
        this);
    Preconditions.checkState(
        containsErrors,
        "contextualizeFailureDetailForTarget called for package not in error. target=%s",
        target);
    String prefix =
        "Target '" + target.getLabel() + "' contains an error and its package is in error";
    if (failureDetail == null) {
      return FailureDetail.newBuilder()
          .setMessage(prefix)
          .setPackageLoading(PackageLoading.newBuilder().setCode(Code.TARGET_MISSING))
          .build();
    }
    return failureDetail.toBuilder().setMessage(prefix + ": " + failureDetail.getMessage()).build();
  }

  /** Returns an (immutable, ordered) view of all the targets belonging to this package. */
  public ImmutableSortedMap<String, Target> getTargets() {
    return targets;
  }

  /** Common getTargets implementation, accessible by {@link Package.Builder}. */
  private static Set<Target> getTargets(BiMap<String, Target> targetMap) {
    return targetMap.values();
  }

  /**
   * Returns a (read-only, ordered) iterable of all the targets belonging to this package which are
   * instances of the specified class.
   */
  public <T extends Target> Iterable<T> getTargets(Class<T> targetClass) {
    return getTargets(targets, targetClass);
  }

  /**
   * Common getTargets implementation, accessible by both {@link Package} and {@link
   * Package.Builder}.
   */
  private static <T extends Target> Iterable<T> getTargets(
      Map<String, Target> targetMap, Class<T> targetClass) {
    return Iterables.filter(targetMap.values(), targetClass);
  }

  /**
   * Returns the rule that corresponds to a particular BUILD target name. Useful for walking through
   * the dependency graph of a target. Fails if the target is not a Rule.
   */
  public Rule getRule(String targetName) {
    return (Rule) targets.get(targetName);
  }

  /** Returns this package's workspace name. */
  public String getWorkspaceName() {
    return metadata.workspaceName;
  }

  /**
   * Returns the target (a member of this package) whose name is "targetName". First rules are
   * searched, then output files, then input files. The target name must be valid, as defined by
   * {@code LabelValidator#validateTargetName}.
   *
   * @throws NoSuchTargetException if the specified target was not found.
   */
  public Target getTarget(String targetName) throws NoSuchTargetException {
    Target target = targets.get(targetName);
    if (target != null) {
      return target;
    }

    Label label;
    try {
      label = Label.create(metadata.packageIdentifier, targetName);
    } catch (LabelSyntaxException e) {
      throw new IllegalArgumentException(targetName, e);
    }

    if (metadata.succinctTargetNotFoundErrors) {
      throw new NoSuchTargetException(
          label, String.format("target '%s' not declared in package '%s'", targetName, getName()));
    } else {
      String alternateTargetSuggestion = getAlternateTargetSuggestion(targetName);
      throw new NoSuchTargetException(
          label,
          String.format(
              "target '%s' not declared in package '%s' defined by %s%s",
              targetName,
              getName(),
              metadata.filename.asPath().getPathString(),
              alternateTargetSuggestion));
    }
  }

  private String getAlternateTargetSuggestion(String targetName) {
    // If there's a file on the disk that's not mentioned in the BUILD file,
    // produce a more informative error.  NOTE! this code path is only executed
    // on failure, which is (relatively) very rare.  In the common case no
    // stat(2) is executed.
    Path filename = metadata.packageDirectory.getRelative(targetName);
    if (!PathFragment.isNormalized(targetName) || "*".equals(targetName)) {
      // Don't check for file existence if the target name is not normalized
      // because the error message would be confusing and wrong. If the
      // targetName is "foo/bar/.", and there is a directory "foo/bar", it
      // doesn't mean that "//pkg:foo/bar/." is a valid label.
      // Also don't check if the target name is a single * character since
      // it's invalid on Windows.
      return "";
    } else if (filename.isDirectory()) {
      return "; however, a source directory of this name exists.  (Perhaps add "
          + "'exports_files([\""
          + targetName
          + "\"])' to "
          + getName()
          + "/BUILD, or define a "
          + "filegroup?)";
    } else if (filename.exists()) {
      return "; however, a source file of this name exists.  (Perhaps add "
          + "'exports_files([\""
          + targetName
          + "\"])' to "
          + getName()
          + "/BUILD?)";
    } else {
      return TargetSuggester.suggestTargets(targetName, targets.keySet());
    }
  }

  /**
   * How to enforce visibility on <code>config_setting</code> See {@link
   * ConfigSettingVisibilityPolicy} for details.
   */
  public ConfigSettingVisibilityPolicy getConfigSettingVisibilityPolicy() {
    return metadata.configSettingVisibilityPolicy;
  }

  public ImmutableList<TargetPattern> getRegisteredExecutionPlatforms() {
    return registeredExecutionPlatforms;
  }

  public ImmutableList<TargetPattern> getRegisteredToolchains() {
    return registeredToolchains;
  }

  public ImmutableList<TargetPattern> getUserRegisteredToolchains() {
    return getRegisteredToolchains()
        .subList(
            0, firstWorkspaceSuffixRegisteredToolchain.orElse(getRegisteredToolchains().size()));
  }

  public ImmutableList<TargetPattern> getWorkspaceSuffixRegisteredToolchains() {
    return getRegisteredToolchains()
        .subList(
            firstWorkspaceSuffixRegisteredToolchain.orElse(getRegisteredToolchains().size()),
            getRegisteredToolchains().size());
  }

  OptionalInt getFirstWorkspaceSuffixRegisteredToolchain() {
    return firstWorkspaceSuffixRegisteredToolchain;
  }

  @Override
  public String toString() {
    return "Package("
        + getName()
        + ")="
        + (targets != null ? getTargets(Rule.class) : "initializing...");
  }

  /**
   * Dumps the package for debugging. Do not depend on the exact format/contents of this debugging
   * output.
   */
  public void dump(PrintStream out) {
    out.println("  Package " + getName() + " (" + metadata.filename.asPath() + ")");

    // Rules:
    out.println("    Rules");
    for (Rule rule : getTargets(Rule.class)) {
      out.println("      " + rule.getTargetKind() + " " + rule.getLabel());
      for (Attribute attr : rule.getAttributes()) {
        for (Object possibleValue :
            AggregatingAttributeMapper.of(rule).visitAttribute(attr.getName(), attr.getType())) {
          out.println("        " + attr.getName() + " = " + possibleValue);
        }
      }
    }

    // Files:
    out.println("    Files");
    for (FileTarget file : getTargets(FileTarget.class)) {
      out.print("      " + file.getTargetKind() + " " + file.getLabel());
      if (file instanceof OutputFile) {
        out.println(" (generated by " + ((OutputFile) file).getGeneratingRule().getLabel() + ")");
      } else {
        out.println();
      }
    }
  }

  public static Builder newExternalPackageBuilder(
      PackageSettings helper,
      RootedPath workspacePath,
      String workspaceName,
      RepositoryMapping mainRepoMapping,
      boolean noImplicitFileExport,
      PackageOverheadEstimator packageOverheadEstimator) {
    return new Builder(
            helper,
            LabelConstants.EXTERNAL_PACKAGE_IDENTIFIER,
            workspaceName,
            /* associatedModuleName= */ Optional.empty(),
            /* associatedModuleVersion= */ Optional.empty(),
            noImplicitFileExport,
            mainRepoMapping,
            mainRepoMapping,
            /* cpuBoundSemaphore= */ null,
            packageOverheadEstimator)
        .setFilename(workspacePath);
  }

  public static Builder newExternalPackageBuilderForBzlmod(
      RootedPath moduleFilePath,
      boolean noImplicitFileExport,
      PackageIdentifier basePackageId,
      RepositoryMapping repoMapping) {
    return new Builder(
            PackageSettings.DEFAULTS,
            basePackageId,
            DUMMY_WORKSPACE_NAME_FOR_BZLMOD_PACKAGES,
            /* associatedModuleName= */ Optional.empty(),
            /* associatedModuleVersion= */ Optional.empty(),
            noImplicitFileExport,
            repoMapping,
            // This mapping is *not* the main repository's mapping, but since it is only used to
            // construct a query command in an error message and the package built here can't be
            // seen by query, the particular value does not matter.
            RepositoryMapping.ALWAYS_FALLBACK,
            /* cpuBoundSemaphore= */ null,
            PackageOverheadEstimator.NOOP_ESTIMATOR)
        .setFilename(moduleFilePath)
        .setLoads(ImmutableList.of());
  }

  /**
   * Returns an error {@link Event} with {@link Location} and {@link DetailedExitCode} properties.
   */
  public static Event error(Location location, String message, Code code) {
    Event error = Event.error(location, message);
    return error.withProperty(DetailedExitCode.class, createDetailedCode(message, code));
  }

  private static DetailedExitCode createDetailedCode(String errorMessage, Code code) {
    return DetailedExitCode.of(
        FailureDetail.newBuilder()
            .setMessage(errorMessage)
            .setPackageLoading(PackageLoading.newBuilder().setCode(code))
            .build());
  }

  /**
   * A builder for {@link Package} objects. Only intended to be used by {@link PackageFactory} and
   * {@link com.google.devtools.build.lib.skyframe.PackageFunction}.
   */
  public static class Builder {

    /**
     * A bundle of options affecting package construction, that is not specific to any particular
     * package.
     */
    public interface PackageSettings {
      /**
       * Returns whether or not extra detail should be added to {@link NoSuchTargetException}s
       * thrown from {@link #getTarget}. Useful for toning down verbosity in situations where it can
       * be less helpful.
       */
      default boolean succinctTargetNotFoundErrors() {
        return false;
      }

      /**
       * Determines whether to precompute a list of transitively loaded starlark files while
       * building packages.
       *
       * <p>Typically, direct loads are stored as a {@code ImmutableList<Module>}. This is
       * sufficient to reconstruct the full load graph by recursively traversing {@link
       * BazelModuleContext#loads}. If the package is going to be serialized, however, it may make
       * more sense to precompute a flat list containing the labels of all transitively loaded bzl
       * files since {@link Module} is costly to serialize.
       *
       * <p>If this returns {@code true}, transitive loads are stored as an {@code
       * ImmutableList<Label>} and direct loads are not stored.
       */
      default boolean precomputeTransitiveLoads() {
        return false;
      }

      PackageSettings DEFAULTS = new PackageSettings() {};
    }

    /**
     * The output instance for this builder. Needs to be instantiated and available with name info
     * throughout initialization. All other settings are applied during {@link #build}. See {@link
     * Package#Package} and {@link Package#finishInit} for details.
     */
    private final Package pkg;

    private final boolean precomputeTransitiveLoads;
    private final boolean noImplicitFileExport;

    // The map from each repository to that repository's remappings map.
    // This is only used in the //external package, it is an empty map for all other packages.
    private final HashMap<RepositoryName, HashMap<String, RepositoryName>>
        externalPackageRepositoryMappings = new HashMap<>();

    /** Converts label literals to Label objects within this package. */
    private final LabelConverter labelConverter;

    /** Estimates the package overhead of this package. */
    private final PackageOverheadEstimator packageOverheadEstimator;

    /**
     * Semaphore held by the Skyframe thread when performing CPU work.
     *
     * <p>This should be released when performing I/O.
     */
    @Nullable // Only non-null when inside PackageFunction.compute and the semaphore is enabled.
    private final Semaphore cpuBoundSemaphore;

    // TreeMap so that the iteration order of variables is consistent regardless of insertion order
    // (which may change due to serialization). This is useful so that the serialized representation
    // is deterministic.
    private final TreeMap<String, String> makeEnv = new TreeMap<>();
    private final List<Event> events = Lists.newArrayList();
    private final List<Postable> posts = Lists.newArrayList();
    // Assigned by setLocalEventHandler, but not necessarily in all contexts.
    // TODO(#19922): Make non-nullable, init in constructor.
    @Nullable private StoredEventHandler localEventHandler = null;
    @Nullable private String ioExceptionMessage = null;
    @Nullable private IOException ioException = null;
    @Nullable private DetailedExitCode ioExceptionDetailedExitCode = null;
    // TODO(#19922): Consider having separate containsErrors fields on Metadata and Package. In that
    // case, this field is replaced by the one on Metadata.
    private boolean containsErrors = false;
    // A package's FailureDetail field derives from its Builder's events. During package
    // deserialization, those events are unavailable, because those events aren't serialized [*].
    // Its FailureDetail value is serialized, however. During deserialization, that value is
    // assigned here, so that it can be assigned to the deserialized package.
    //
    // Likewise, during workspace part assembly, errors from parent parts should propagate to their
    // children.
    //
    // [*] Not in the context of the package, anyway. Skyframe values containing a package may
    // serialize events emitted during its construction/evaluation.
    @Nullable private FailureDetail failureDetailOverride = null;

    // Used by glob(). Null for contexts where glob() is disallowed, including WORKSPACE files and
    // some tests.
    @Nullable private Globber globber = null;

    // All targets added to the package. We use SnapshottableBiMap to help track insertion order of
    // Rule targets, for use by native.existing_rules().
    private BiMap<String, Target> targets =
        new SnapshottableBiMap<>(target -> target instanceof Rule);
    private final Map<Label, EnvironmentGroup> environmentGroups = new HashMap<>();

    /**
     * Stores labels for each rule so that we don't have to call the costly {@link Rule#getLabels}
     * twice (once for {@link #checkForInputOutputConflicts} and once for {@link #beforeBuild}).
     *
     * <p>Remains {@code null} when rules are added via {@link #addRuleUnchecked}, which occurs with
     * package deserialization. Set back to {@code null} after building.
     */
    @Nullable private Map<Rule, List<Label>> ruleLabels = null;

    private final List<TargetPattern> registeredExecutionPlatforms = new ArrayList<>();
    private final List<TargetPattern> registeredToolchains = new ArrayList<>();

    /**
     * Tracks the index within {@link #registeredToolchains} of the first toolchain registered from
     * the WORKSPACE suffixes rather than the WORKSPACE file (if any).
     *
     * <p>This is needed to distinguish between these toolchains during resolution: toolchains
     * registered in WORKSPACE have precedence over those defined in non-root Bazel modules, which
     * in turn have precedence over those from the WORKSPACE suffixes.
     */
    private OptionalInt firstWorkspaceSuffixRegisteredToolchain = OptionalInt.empty();

    /** True iff the "package" function has already been called in this package. */
    private boolean packageFunctionUsed;

    /**
     * The collection of the prefixes of every output file. Maps every prefix to an output file
     * whose prefix it is.
     *
     * <p>This is needed to make the output file prefix conflict check be reasonably fast. However,
     * since it can potentially take a lot of memory and is useless after the package has been
     * loaded, it isn't passed to the package itself.
     */
    private final Map<String, OutputFile> outputFilePrefixes = new HashMap<>();

    private final Interner<ImmutableList<?>> listInterner = new ThreadCompatibleInterner<>();

    private ImmutableMap<Location, String> generatorMap = ImmutableMap.of();

    private final TestSuiteImplicitTestsAccumulator testSuiteImplicitTestsAccumulator =
        new TestSuiteImplicitTestsAccumulator();

    /** Returns the "generator_name" to use for a given call site location in a BUILD file. */
    @Nullable
    String getGeneratorNameByLocation(Location loc) {
      return generatorMap.get(loc);
    }

    /** Sets the package's map of "generator_name" values keyed by the location of the call site. */
    // TODO(#19922): Require this to be set before BUILD evaluation.
    @CanIgnoreReturnValue
    public Builder setGeneratorMap(ImmutableMap<Location, String> map) {
      this.generatorMap = map;
      return this;
    }

    /**
     * Returns the value to use for {@code test_suite}s' {@code $implicit_tests} attribute, as-is,
     * when the {@code test_suite} doesn't specify an explicit, non-empty {@code tests} value. The
     * returned list is mutated by the package-building process - it may be observed to be empty or
     * incomplete before package loading is complete. When package loading is complete it will
     * contain the label of each non-manual test matching the provided tags in the package, in label
     * order.
     *
     * <p>This method <b>MUST</b> be called before the package is built - otherwise the requested
     * implicit tests won't be accumulated.
     */
    List<Label> getTestSuiteImplicitTestsRef(List<String> tags) {
      return testSuiteImplicitTestsAccumulator.getTestSuiteImplicitTestsRefForTags(tags);
    }

    @ThreadCompatible
    private static final class ThreadCompatibleInterner<T> implements Interner<T> {
      private final Map<T, T> interns = new HashMap<>();

      @Override
      public T intern(T sample) {
        T existing = interns.putIfAbsent(sample, sample);
        return firstNonNull(existing, sample);
      }
    }

    private boolean alreadyBuilt = false;

    Builder(
        PackageSettings packageSettings,
        PackageIdentifier id,
        String workspaceName,
        Optional<String> associatedModuleName,
        Optional<String> associatedModuleVersion,
        boolean noImplicitFileExport,
        RepositoryMapping repositoryMapping,
        // TODO(#19922): Spurious parameter, delete.
        RepositoryMapping mainRepositoryMapping,
        @Nullable Semaphore cpuBoundSemaphore,
        PackageOverheadEstimator packageOverheadEstimator) {
      Metadata metadata = new Metadata();
      metadata.packageIdentifier = Preconditions.checkNotNull(id);
      metadata.workspaceName = Preconditions.checkNotNull(workspaceName);
      metadata.repositoryMapping = Preconditions.checkNotNull(repositoryMapping);
      metadata.associatedModuleName = Preconditions.checkNotNull(associatedModuleName);
      metadata.associatedModuleVersion = Preconditions.checkNotNull(associatedModuleVersion);
      metadata.succinctTargetNotFoundErrors = packageSettings.succinctTargetNotFoundErrors();

      this.pkg = new Package(metadata);
      this.precomputeTransitiveLoads = packageSettings.precomputeTransitiveLoads();
      this.noImplicitFileExport = noImplicitFileExport;
      this.labelConverter = new LabelConverter(id, repositoryMapping);
      if (pkg.getName().startsWith("javatests/")) {
        mergePackageArgsFrom(PackageArgs.builder().setDefaultTestOnly(true));
      }
      this.cpuBoundSemaphore = cpuBoundSemaphore;
      this.packageOverheadEstimator = packageOverheadEstimator;
    }

    PackageIdentifier getPackageIdentifier() {
      return pkg.getPackageIdentifier();
    }

    /**
     * Determine whether this package should contain build rules (returns {@code false}) or repo
     * rules (returns {@code true}).
     */
    boolean isRepoRulePackage() {
      return pkg.isRepoRulePackage();
    }

    String getPackageWorkspaceName() {
      return pkg.getWorkspaceName();
    }

    /**
     * Returns the name of the Bzlmod module associated with the repo this package is in. If this
     * package is not from a Bzlmod repo, this is empty. For repos generated by module extensions,
     * this is the name of the module hosting the extension.
     */
    Optional<String> getAssociatedModuleName() {
      return pkg.metadata.associatedModuleName;
    }

    /**
     * Returns the version of the Bzlmod module associated with the repo this package is in. If this
     * package is not from a Bzlmod repo, this is empty. For repos generated by module extensions,
     * this is the version of the module hosting the extension.
     */
    Optional<String> getAssociatedModuleVersion() {
      return pkg.metadata.associatedModuleVersion;
    }

    /**
     * Updates the externalPackageRepositoryMappings entry for {@code repoWithin}. Adds new entry
     * from {@code localName} to {@code mappedName} in {@code repoWithin}'s map.
     *
     * @param repoWithin the RepositoryName within which the mapping should apply
     * @param localName the name that actually appears in the WORKSPACE and BUILD files in the
     *     {@code repoWithin} repository
     * @param mappedName the RepositoryName by which localName should be referenced
     */
    @CanIgnoreReturnValue
    Builder addRepositoryMappingEntry(
        RepositoryName repoWithin, String localName, RepositoryName mappedName) {
      HashMap<String, RepositoryName> mapping =
          externalPackageRepositoryMappings.computeIfAbsent(
              repoWithin, (RepositoryName k) -> new HashMap<>());
      mapping.put(localName, mappedName);
      return this;
    }

    /** Adds all the mappings from a given {@link Package}. */
    @CanIgnoreReturnValue
    Builder addRepositoryMappings(Package aPackage) {
      ImmutableMap<RepositoryName, ImmutableMap<String, RepositoryName>> repositoryMappings =
          aPackage.externalPackageRepositoryMappings;
      for (Map.Entry<RepositoryName, ImmutableMap<String, RepositoryName>> repositoryName :
          repositoryMappings.entrySet()) {
        for (Map.Entry<String, RepositoryName> repositoryNameRepositoryNameEntry :
            repositoryName.getValue().entrySet()) {
          addRepositoryMappingEntry(
              repositoryName.getKey(),
              repositoryNameRepositoryNameEntry.getKey(),
              repositoryNameRepositoryNameEntry.getValue());
        }
      }
      return this;
    }

    public LabelConverter getLabelConverter() {
      return labelConverter;
    }

    Interner<ImmutableList<?>> getListInterner() {
      return listInterner;
    }

    /** Sets the name of this package's BUILD file. */
    // TODO(#19922): Require this to be set before BUILD evaluation.
    @CanIgnoreReturnValue
    public Builder setFilename(RootedPath filename) {
      pkg.metadata.filename = filename;
      pkg.metadata.packageDirectory = filename.asPath().getParentDirectory();
      try {
        pkg.metadata.buildFileLabel = createLabel(filename.getRootRelativePath().getBaseName());
        addInputFile(pkg.metadata.buildFileLabel, Location.fromFile(filename.asPath().toString()));
      } catch (LabelSyntaxException e) {
        // This can't actually happen.
        throw new AssertionError("Package BUILD file has an illegal name: " + filename, e);
      }
      return this;
    }

    public Label getBuildFileLabel() {
      return pkg.metadata.buildFileLabel;
    }

    /**
     * Return a read-only copy of the name mapping of external repositories for a given repository.
     * Reading that mapping directly from the builder allows to also take mappings into account that
     * are only discovered while constructing the external package (e.g., the mapping of the name of
     * the main workspace to the canonical main name '@').
     */
    RepositoryMapping getRepositoryMappingFor(RepositoryName name) {
      Map<String, RepositoryName> mapping = externalPackageRepositoryMappings.get(name);
      if (mapping == null) {
        return RepositoryMapping.ALWAYS_FALLBACK;
      } else {
        return RepositoryMapping.createAllowingFallback(mapping);
      }
    }

    RootedPath getFilename() {
      return pkg.metadata.filename;
    }

    /**
     * Returns {@link Postable}s accumulated while building the package.
     *
     * <p>Should retrieved and reported as close to after {@link #build()} or {@link #finishBuild()}
     * as possible - any earlier and the data may be incomplete.
     */
    public List<Postable> getPosts() {
      return posts;
    }

    /**
     * Returns {@link Event}s accumulated while building the package.
     *
     * <p>Should retrieved and reported as close to after {@link #build()} or {@link #finishBuild()}
     * as possible - any earlier and the data may be incomplete.
     */
    public List<Event> getEvents() {
      return events;
    }

    /** Associates a {@link StoredEventHandler} with this builder. */
    // TODO(#19922): This is a temporary method resulting from migrating PackageContext.eventHandler
    // to Package.Builder. The next step is to create the StoredEventHandler in Package.Builder's
    // constructor, and use that to eliminate the separate `events` and `posts` fields.
    @CanIgnoreReturnValue
    Builder setLocalEventHandler(StoredEventHandler eventHandler) {
      this.localEventHandler = eventHandler;
      return this;
    }

    /**
     * Returns the {@link ExtendedEventHandler} associated with this builder. Using this handler
     * <i>should</i> be equivalent to calling {@link #addEvent} / {@link #addPosts}.
     *
     * <p>This field may be null in tests.
     */
    // TODO(#19922): The "should" in the above javadoc will be guaranteed by eliminating the
    // separate `events` and `posts` fields. We'll also make this non-nullable.
    @Nullable
    public ExtendedEventHandler getLocalEventHandler() {
      return localEventHandler;
    }

    @CanIgnoreReturnValue
    public Builder setMakeVariable(String name, String value) {
      makeEnv.put(name, value);
      return this;
    }

    @CanIgnoreReturnValue
    public Builder mergePackageArgsFrom(PackageArgs packageArgs) {
      pkg.metadata.packageArgs = pkg.metadata.packageArgs.mergeWith(packageArgs);
      return this;
    }

    @CanIgnoreReturnValue
    public Builder mergePackageArgsFrom(PackageArgs.Builder builder) {
      return mergePackageArgsFrom(builder.build());
    }

    /** Called partial b/c in builder and thus subject to mutation and updates */
    public PackageArgs getPartialPackageArgs() {
      return pkg.metadata.packageArgs;
    }

    /** Sets visibility enforcement policy for <code>config_setting</code>. */
    // TODO(#19922): Require this to be set before BUILD evaluation.
    @CanIgnoreReturnValue
    public Builder setConfigSettingVisibilityPolicy(ConfigSettingVisibilityPolicy policy) {
      this.pkg.metadata.configSettingVisibilityPolicy = policy;
      return this;
    }

    /** Uses the workspace name from {@code //external} to set this package's workspace name. */
    // TODO(#19922): Seems like this is only used for WORKSPACE logic (`workspace()` callable), but
    // it clashes with the notion that, for BUILD files, the workspace name should be supplied to
    // the Builder constructor and not mutated during evaluation. Either put up with this until we
    // delete WORKSPACE logic, or else separate the `workspace()` callable's mutation from this
    // metadata field.
    @CanIgnoreReturnValue
    @VisibleForTesting
    public Builder setWorkspaceName(String workspaceName) {
      pkg.metadata.workspaceName = workspaceName;
      return this;
    }

    /** Returns whether the "package" function has been called yet */
    boolean isPackageFunctionUsed() {
      return packageFunctionUsed;
    }

    void setPackageFunctionUsed() {
      packageFunctionUsed = true;
    }

    /** Sets the number of Starlark computation steps executed by this BUILD file. */
    void setComputationSteps(long n) {
      pkg.computationSteps = n;
    }

    Builder setIOException(IOException e, String message, DetailedExitCode detailedExitCode) {
      this.ioException = e;
      this.ioExceptionMessage = message;
      this.ioExceptionDetailedExitCode = detailedExitCode;
      return setContainsErrors();
    }

    /**
     * Declares that errors were encountering while loading this package. If called, {@link
     * #addEvent} or {@link #addEvents} should already have been called with an {@link Event} of
     * type {@link EventKind#ERROR} that includes a {@link FailureDetail}.
     */
    @CanIgnoreReturnValue
    public Builder setContainsErrors() {
      containsErrors = true;
      return this;
    }

    public boolean containsErrors() {
      return containsErrors;
    }

    @CanIgnoreReturnValue
    Builder addPosts(Iterable<Postable> posts) {
      for (Postable post : posts) {
        this.posts.add(post);
      }
      return this;
    }

    @CanIgnoreReturnValue
    Builder addEvents(Iterable<Event> events) {
      for (Event event : events) {
        addEvent(event);
      }
      return this;
    }

    @CanIgnoreReturnValue
    public Builder addEvent(Event event) {
      this.events.add(event);
      return this;
    }

    void setFailureDetailOverride(FailureDetail failureDetail) {
      failureDetailOverride = failureDetail;
    }

    @Nullable
    FailureDetail getFailureDetail() {
      if (failureDetailOverride != null) {
        return failureDetailOverride;
      }

      List<Event> undetailedEvents = null;
      for (Event event : this.events) {
        if (event.getKind() != EventKind.ERROR) {
          continue;
        }
        DetailedExitCode detailedExitCode = event.getProperty(DetailedExitCode.class);
        if (detailedExitCode != null && detailedExitCode.getFailureDetail() != null) {
          return detailedExitCode.getFailureDetail();
        }
        if (containsErrors) {
          if (undetailedEvents == null) {
            undetailedEvents = new ArrayList<>();
          }
          undetailedEvents.add(event);
        }
      }
      if (undetailedEvents != null) {
        BugReport.sendNonFatalBugReport(
            new IllegalStateException("Package has undetailed error from " + undetailedEvents));
      }
      return null;
    }

    // TODO(#19922): Require this to be set before BUILD evaluation.
    @CanIgnoreReturnValue
    public Builder setLoads(Iterable<Module> directLoads) {
      checkLoadsNotSet();
      if (precomputeTransitiveLoads) {
        pkg.metadata.transitiveLoads = computeTransitiveLoads(directLoads);
      } else {
        pkg.metadata.directLoads = ImmutableList.copyOf(directLoads);
      }
      return this;
    }

    @CanIgnoreReturnValue
    Builder setTransitiveLoadsForDeserialization(ImmutableList<Label> transitiveLoads) {
      checkLoadsNotSet();
      pkg.metadata.transitiveLoads = Preconditions.checkNotNull(transitiveLoads);
      return this;
    }

    private void checkLoadsNotSet() {
      Preconditions.checkState(
          pkg.metadata.directLoads == null,
          "Direct loads already set: %s",
          pkg.metadata.directLoads);
      Preconditions.checkState(
          pkg.metadata.transitiveLoads == null,
          "Transitive loads already set: %s",
          pkg.metadata.transitiveLoads);
    }

    /** Sets the {@link Globber}. */
    // TODO(#19922): Move this to Builder() constructor.
    @CanIgnoreReturnValue
    public Builder setGlobber(Globber globber) {
      Preconditions.checkState(this.globber == null);
      this.globber = globber;
      return this;
    }

    /**
     * Returns the {@link Globber} used to implement {@code glob()} functionality during BUILD
     * evaluation. Null for contexts where globbing is not possible, including WORKSPACE files and
     * some tests.
     */
    @Nullable
    public Globber getGlobber() {
      return globber;
    }

    /**
     * Creates a new {@link Rule} {@code r} where {@code r.getPackage()} is the {@link Package}
     * associated with this {@link Builder}.
     *
     * <p>The created {@link Rule} will have no output files and therefore will be in an invalid
     * state.
     */
    Rule createRule(
        Label label, RuleClass ruleClass, List<StarlarkThread.CallStackEntry> callstack) {
      return createRule(
          label,
          ruleClass,
          callstack.isEmpty() ? Location.BUILTIN : callstack.get(0).location,
          CallStack.compactInterior(callstack));
    }

    Rule createRule(
        Label label,
        RuleClass ruleClass,
        Location location,
        @Nullable CallStack.Node interiorCallStack) {
      return new Rule(pkg, label, ruleClass, location, interiorCallStack);
    }

    @Nullable
    Target getTarget(String name) {
      return targets.get(name);
    }

    /**
     * Replaces a target in the {@link Package} under construction with a new target with the same
     * name and belonging to the same package.
     *
     * <p>A hack needed for {@link WorkspaceFactoryHelper}.
     */
    void replaceTarget(Target newTarget) {
      Preconditions.checkArgument(
          targets.containsKey(newTarget.getName()),
          "No existing target with name '%s' in the targets map",
          newTarget.getName());
      Preconditions.checkArgument(
          newTarget.getPackage() == pkg, // pointer comparison since we're constructing `pkg`
          "Replacement target belongs to package '%s', expected '%s'",
          newTarget.getPackage(),
          pkg);
      Target oldTarget = targets.put(newTarget.getName(), newTarget);
      if (newTarget instanceof Rule && ruleLabels != null) {
        List<Label> ruleLabelsForOldTarget = ruleLabels.remove(oldTarget);
        if (ruleLabelsForOldTarget != null) {
          ruleLabels.put((Rule) newTarget, ruleLabelsForOldTarget);
        }
      }
    }

    public Set<Target> getTargets() {
      return Package.getTargets(targets);
    }

    /**
     * Returns a lightweight snapshot view of the names of all rule targets belonging to this
     * package at the time of this call.
     *
     * @throws IllegalStateException if this method is called after {@link #beforeBuild} has been
     *     called.
     */
    Map<String, Rule> getRulesSnapshotView() {
      if (targets instanceof SnapshottableBiMap<?, ?>) {
        return Maps.transformValues(
            ((SnapshottableBiMap<String, Target>) targets).getTrackedSnapshot(),
            target -> (Rule) target);
      } else {
        throw new IllegalStateException(
            "getRulesSnapshotView() cannot be used after beforeBuild() has been called");
      }
    }

    /**
     * Returns an {@link Iterable} of all the rule instance targets belonging to this package.
     *
     * <p>The returned {@link Iterable} will be deterministically ordered, in the order the rule
     * instance targets were instantiated.
     */
    private Iterable<Rule> getRules() {
      return Package.getTargets(targets, Rule.class);
    }

    /** An input file name conflicts with an existing package member. */
    static class GeneratedLabelConflict extends NameConflictException {
      private GeneratedLabelConflict(String message) {
        super(message);
      }
    }

    /**
     * Creates an input file target in this package with the specified name.
     *
     * @param targetName name of the input file. This must be a valid target name as defined by
     *     {@link com.google.devtools.build.lib.cmdline.LabelValidator#validateTargetName}.
     * @return the newly-created InputFile, or the old one if it already existed.
     * @throws GeneratedLabelConflict if the name was already taken by a Rule or an OutputFile
     *     target.
     * @throws IllegalArgumentException if the name is not a valid label
     */
    InputFile createInputFile(String targetName, Location location) throws GeneratedLabelConflict {
      Target existing = targets.get(targetName);
      if (existing == null) {
        try {
          return addInputFile(createLabel(targetName), location);
        } catch (LabelSyntaxException e) {
          throw new IllegalArgumentException(
              "FileTarget in package " + pkg.getName() + " has illegal name: " + targetName, e);
        }
      } else if (existing instanceof InputFile) {
        return (InputFile) existing; // idempotent
      } else {
        throw new GeneratedLabelConflict(
            "generated label '//"
                + pkg.getName()
                + ":"
                + targetName
                + "' conflicts with existing "
                + existing.getTargetKind());
      }
    }

    /**
     * Sets the visibility and license for an input file. The input file must already exist as a
     * member of this package.
     *
     * @throws IllegalArgumentException if the input file doesn't exist in this package's target
     *     map.
     */
    void setVisibilityAndLicense(InputFile inputFile, RuleVisibility visibility, License license) {
      String filename = inputFile.getName();
      Target cacheInstance = targets.get(filename);
      if (!(cacheInstance instanceof InputFile)) {
        throw new IllegalArgumentException(
            "Can't set visibility for nonexistent FileTarget "
                + filename
                + " in package "
                + pkg.getName()
                + ".");
      }
      if (!((InputFile) cacheInstance).isVisibilitySpecified()
          || cacheInstance.getVisibility() != visibility
          || !Objects.equals(cacheInstance.getLicense(), license)) {
        targets.put(
            filename,
            new VisibilityLicenseSpecifiedInputFile(
                pkg, cacheInstance.getLabel(), cacheInstance.getLocation(), visibility, license));
      }
    }

    /**
     * Creates a label for a target inside this package.
     *
     * @throws LabelSyntaxException if the {@code targetName} is invalid
     */
    Label createLabel(String targetName) throws LabelSyntaxException {
      return Label.create(pkg.getPackageIdentifier(), targetName);
    }

    /** Adds a package group to the package. */
    void addPackageGroup(
        String name,
        Collection<String> packages,
        Collection<Label> includes,
        boolean allowPublicPrivate,
        boolean repoRootMeansCurrentRepo,
        EventHandler eventHandler,
        Location location)
        throws NameConflictException, LabelSyntaxException {
      PackageGroup group =
          new PackageGroup(
              createLabel(name),
              pkg,
              packages,
              includes,
              allowPublicPrivate,
              repoRootMeansCurrentRepo,
              eventHandler,
              location);
      Target existing = targets.get(group.getName());
      if (existing != null) {
        throw nameConflict(group, existing);
      }

      targets.put(group.getName(), group);

      if (group.containsErrors()) {
        setContainsErrors();
      }
    }

    /**
     * Returns true if any labels in the given list appear multiple times, reporting an appropriate
     * error message if so.
     *
     * <p>TODO(bazel-team): apply this to all build functions (maybe automatically?), possibly
     * integrate with RuleClass.checkForDuplicateLabels.
     */
    private static boolean hasDuplicateLabels(
        List<Label> labels,
        String owner,
        String attrName,
        Location location,
        EventHandler eventHandler) {
      Set<Label> dupes = CollectionUtils.duplicatedElementsOf(labels);
      for (Label dupe : dupes) {
        eventHandler.handle(
            error(
                location,
                String.format(
                    "label '%s' is duplicated in the '%s' list of '%s'", dupe, attrName, owner),
                Code.DUPLICATE_LABEL));
      }
      return !dupes.isEmpty();
    }

    /** Adds an environment group to the package. */
    void addEnvironmentGroup(
        String name,
        List<Label> environments,
        List<Label> defaults,
        EventHandler eventHandler,
        Location location)
        throws NameConflictException, LabelSyntaxException {

      if (hasDuplicateLabels(environments, name, "environments", location, eventHandler)
          || hasDuplicateLabels(defaults, name, "defaults", location, eventHandler)) {
        setContainsErrors();
        return;
      }

      EnvironmentGroup group =
          new EnvironmentGroup(createLabel(name), pkg, environments, defaults, location);
      Target existing = targets.get(group.getName());
      if (existing != null) {
        throw nameConflict(group, existing);
      }

      targets.put(group.getName(), group);
      // Invariant: once group is inserted into targets, it must also:
      // (a) be inserted into environmentGroups, or
      // (b) have its group.processMemberEnvironments called.
      // Otherwise it will remain uninitialized,
      // causing crashes when it is later toString-ed.

      for (Event error : group.validateMembership()) {
        eventHandler.handle(error);
        setContainsErrors();
      }

      // For each declared environment, make sure it doesn't also belong to some other group.
      for (Label environment : group.getEnvironments()) {
        EnvironmentGroup otherGroup = environmentGroups.get(environment);
        if (otherGroup != null) {
          eventHandler.handle(
              error(
                  location,
                  String.format(
                      "environment %s belongs to both %s and %s",
                      environment, group.getLabel(), otherGroup.getLabel()),
                  Code.ENVIRONMENT_IN_MULTIPLE_GROUPS));
          setContainsErrors();
          // Ensure the orphan gets (trivially) initialized.
          group.processMemberEnvironments(ImmutableMap.of());
        } else {
          environmentGroups.put(environment, group);
        }
      }
    }

    /**
     * Same as {@link #addRule}, except with no name conflict checks.
     *
     * <p>Don't call this function unless you know what you're doing.
     */
    void addRuleUnchecked(Rule rule) {
      Preconditions.checkArgument(rule.getPackage() == pkg);
      // Now, modify the package:
      for (OutputFile outputFile : rule.getOutputFiles()) {
        targets.put(outputFile.getName(), outputFile);
        PathFragment outputFileFragment = PathFragment.create(outputFile.getName());
        int segmentCount = outputFileFragment.segmentCount();
        for (int i = 1; i < segmentCount; i++) {
          String prefix = outputFileFragment.subFragment(0, i).toString();
          outputFilePrefixes.putIfAbsent(prefix, outputFile);
        }
      }
      targets.put(rule.getName(), rule);
      if (rule.containsErrors()) {
        this.setContainsErrors();
      }
    }

    void addRule(Rule rule) throws NameConflictException {
      List<Label> labels = rule.getLabels();
      checkForConflicts(rule, labels);
      addRuleUnchecked(rule);
      if (ruleLabels == null) {
        ruleLabels = new HashMap<>();
      }
      ruleLabels.put(rule, labels);
    }

    void addRegisteredExecutionPlatforms(List<TargetPattern> platforms) {
      this.registeredExecutionPlatforms.addAll(platforms);
    }

    void addRegisteredToolchains(List<TargetPattern> toolchains, boolean forWorkspaceSuffix) {
      if (forWorkspaceSuffix && firstWorkspaceSuffixRegisteredToolchain.isEmpty()) {
        firstWorkspaceSuffixRegisteredToolchain = OptionalInt.of(registeredToolchains.size());
      }
      this.registeredToolchains.addAll(toolchains);
    }

    void setFirstWorkspaceSuffixRegisteredToolchain(
        OptionalInt firstWorkspaceSuffixRegisteredToolchain) {
      this.firstWorkspaceSuffixRegisteredToolchain = firstWorkspaceSuffixRegisteredToolchain;
    }

    @CanIgnoreReturnValue
    private Builder beforeBuild(boolean discoverAssumedInputFiles) throws NoSuchPackageException {
      // TODO(#19922): Won't have to check filename/buildFileLabel if we merge setFilename into the
      // Builder constructor.
      Preconditions.checkNotNull(pkg.metadata.filename);
      Preconditions.checkNotNull(pkg.metadata.buildFileLabel);
      if (ioException != null) {
        throw new NoSuchPackageException(
            getPackageIdentifier(), ioExceptionMessage, ioException, ioExceptionDetailedExitCode);
      }

      // SnapshottableBiMap does not allow removing targets (in order to efficiently track rule
      // insertion order). However, we *do* need to support removal of targets in
      // PackageFunction.handleLabelsCrossingSubpackagesAndPropagateInconsistentFilesystemExceptions
      // which is called *between* calls to beforeBuild and finishBuild. We thus repoint the targets
      // map to the SnapshottableBiMap's underlying bimap and thus stop tracking insertion order.
      // After this point, snapshots of targets should no longer be used, and any further
      // getRulesSnapshotView calls will throw.
      if (targets instanceof SnapshottableBiMap<?, ?>) {
        targets = ((SnapshottableBiMap<String, Target>) targets).getUnderlyingBiMap();
      }

      // We create an InputFile corresponding to the BUILD file when setFilename is called. However,
      // the visibility of this target may be overridden with an exports_files directive, so we wait
      // until now to obtain the current instance from the targets map.
      pkg.metadata.buildFile =
          (InputFile)
              Preconditions.checkNotNull(targets.get(pkg.metadata.buildFileLabel.getName()));

      // TODO(bazel-team): We run testSuiteImplicitTestsAccumulator here in beforeBuild(), but what
      // if one of the accumulated tests is later removed in PackageFunction, between the call to
      // buildPartial() and finishBuild(), due to a label-crossing-subpackage-boundary error? Seems
      // like that would mean a test_suite is referencing a Target that's been deleted from its
      // Package.

      // Clear tests before discovering them again in order to keep this method idempotent -
      // otherwise we may double-count tests if we're called twice due to a skyframe restart, etc.
      testSuiteImplicitTestsAccumulator.clearAccumulatedTests();

      Map<String, InputFile> newInputFiles = new HashMap<>();
      for (Rule rule : getRules()) {
        if (discoverAssumedInputFiles) {
          // All labels mentioned by a rule that refer to an unknown target in the current package
          // are assumed to be InputFiles, so let's create them. We add them to a temporary map
          // to avoid concurrent modification to this.targets while iterating (via getRules()).
          List<Label> labels = null;
          if (ruleLabels != null) {
            // Can theoretically be absent from the map if the caller used both addRule() and
            // addRuleUnchecked() on the same Builder.
            labels = ruleLabels.get(rule);
          }
          if (labels == null) {
            labels = rule.getLabels();
          }
          for (Label label : labels) {
            if (label.getPackageIdentifier().equals(pkg.getPackageIdentifier())
                && !targets.containsKey(label.getName())
                && !newInputFiles.containsKey(label.getName())) {
              Location loc = rule.getLocation();
              newInputFiles.put(
                  label.getName(),
                  noImplicitFileExport
                      ? new PrivateVisibilityInputFile(pkg, label, loc)
                      : new InputFile(pkg, label, loc));
            }
          }
        }

        testSuiteImplicitTestsAccumulator.processRule(rule);
      }

      // Make sure all accumulated values are sorted for determinism.
      testSuiteImplicitTestsAccumulator.sortTests();

      for (InputFile file : newInputFiles.values()) {
        addInputFile(file);
      }

      return this;
    }

    /** Intended for use by {@link com.google.devtools.build.lib.skyframe.PackageFunction} only. */
    // TODO(bazel-team): It seems like the motivation for this method (added in cl/74794332) is to
    // allow PackageFunction to delete targets that are found to violate the
    // label-crossing-subpackage-boundaries check. Is there a simpler way to express this idea that
    // doesn't make package-building a multi-stage process?
    public Builder buildPartial() throws NoSuchPackageException {
      if (alreadyBuilt) {
        return this;
      }
      return beforeBuild(/* discoverAssumedInputFiles= */ true);
    }

    /** Intended for use by {@link com.google.devtools.build.lib.skyframe.PackageFunction} only. */
    public Package finishBuild() {
      if (alreadyBuilt) {
        return pkg;
      }

      // Freeze targets and distributions.
      for (Rule rule : getRules()) {
        rule.freeze();
      }
      ruleLabels = null;
      targets = Maps.unmodifiableBiMap(targets);

      // Now all targets have been loaded, so we validate the group's member environments.
      for (EnvironmentGroup envGroup : ImmutableSet.copyOf(environmentGroups.values())) {
        List<Event> errors = envGroup.processMemberEnvironments(targets);
        if (!errors.isEmpty()) {
          addEvents(errors);
          setContainsErrors();
        }
      }

      // Build the package.
      pkg.finishInit(this);
      alreadyBuilt = true;
      return pkg;
    }

    public Package build() throws NoSuchPackageException {
      return build(/* discoverAssumedInputFiles= */ true);
    }

    /**
     * Build the package, optionally adding any labels in the package not already associated with a
     * target as an input file.
     */
    Package build(boolean discoverAssumedInputFiles) throws NoSuchPackageException {
      if (alreadyBuilt) {
        return pkg;
      }
      beforeBuild(discoverAssumedInputFiles);
      return finishBuild();
    }

    private InputFile addInputFile(Label label, Location location) {
      return addInputFile(new InputFile(pkg, label, location));
    }

    private InputFile addInputFile(InputFile inputFile) {
      Target prev = targets.put(inputFile.getLabel().getName(), inputFile);
      Preconditions.checkState(prev == null);
      return inputFile;
    }

    /**
     * Precondition check for addRule. We must maintain these invariants of the package:
     *
     * <ul>
     *   <li>Each name refers to at most one target.
     *   <li>No rule with errors is inserted into the package.
     *   <li>The generating rule of every output file in the package must itself be in the package.
     * </ul>
     */
    private void checkForConflicts(Rule rule, List<Label> labels) throws NameConflictException {
      String name = rule.getName();
      Target existing = targets.get(name);
      if (existing != null) {
        throw nameConflict(rule, existing);
      }

      ImmutableList<OutputFile> outputFiles = rule.getOutputFiles();
      Map<String, OutputFile> outputFilesByName =
          Maps.newHashMapWithExpectedSize(outputFiles.size());

      for (OutputFile outputFile : outputFiles) {
        String outputFileName = outputFile.getName();
        if (outputFilesByName.put(outputFileName, outputFile) != null) {
          throw duplicateOutputFile(outputFile, outputFile); // Duplicate within a single rule.
        }
        existing = targets.get(outputFileName);
        if (existing != null) {
          throw duplicateOutputFile(outputFile, existing);
        }

        // Check if this output file is the prefix of an already existing one.
        if (outputFilePrefixes.containsKey(outputFileName)) {
          throw conflictingOutputFile(outputFile, outputFilePrefixes.get(outputFileName));
        }

        // Check if a prefix of this output file matches an already existing one.
        PathFragment outputFileFragment = PathFragment.create(outputFileName);
        int segmentCount = outputFileFragment.segmentCount();
        for (int i = 1; i < segmentCount; i++) {
          String prefix = outputFileFragment.subFragment(0, i).toString();
          if (outputFilesByName.containsKey(prefix)) {
            throw conflictingOutputFile(outputFile, outputFilesByName.get(prefix));
          }
          if (targets.get(prefix) instanceof OutputFile) {
            throw conflictingOutputFile(outputFile, (OutputFile) targets.get(prefix));
          }

          outputFilePrefixes.putIfAbsent(prefix, outputFile);
        }
      }

      checkForInputOutputConflicts(rule, labels, outputFilesByName.keySet());
    }

    /**
     * A utility method that checks for conflicts between input file names and output file names for
     * a rule from a build file.
     *
     * @param rule the rule whose inputs and outputs are to be checked for conflicts.
     * @param labels the rules {@linkplain Rule#getLabels labels}.
     * @param outputFiles a set containing the names of output files to be generated by the rule.
     * @throws NameConflictException if a conflict is found.
     */
    private static void checkForInputOutputConflicts(
        Rule rule, List<Label> labels, Set<String> outputFiles) throws NameConflictException {
      PackageIdentifier packageIdentifier = rule.getLabel().getPackageIdentifier();
      for (Label inputLabel : labels) {
        if (packageIdentifier.equals(inputLabel.getPackageIdentifier())
            && outputFiles.contains(inputLabel.getName())) {
          throw inputOutputNameConflict(rule, inputLabel.getName());
        }
      }
    }

    /** An output file conflicts with another output file or the BUILD file. */
    private static NameConflictException duplicateOutputFile(
        OutputFile duplicate, Target existing) {
      return new NameConflictException(
          duplicate.getTargetKind()
              + " '"
              + duplicate.getName()
              + "' in rule '"
              + duplicate.getGeneratingRule().getName()
              + "' "
              + conflictsWith(existing));
    }

    /** The package contains two targets with the same name. */
    private static NameConflictException nameConflict(Target duplicate, Target existing) {
      return new NameConflictException(
          duplicate.getTargetKind()
              + " '"
              + duplicate.getName()
              + "' in package '"
              + duplicate.getLabel().getPackageName()
              + "' "
              + conflictsWith(existing));
    }

    /** A a rule has a input/output name conflict. */
    private static NameConflictException inputOutputNameConflict(
        Rule rule, String conflictingName) {
      return new NameConflictException(
          "rule '"
              + rule.getName()
              + "' has file '"
              + conflictingName
              + "' as both an input and an output");
    }

    private static NameConflictException conflictingOutputFile(
        OutputFile added, OutputFile existing) {
      if (added.getGeneratingRule() == existing.getGeneratingRule()) {
        return new NameConflictException(
            String.format(
                "rule '%s' has conflicting output files '%s' and '%s'",
                added.getGeneratingRule().getName(), added.getName(), existing.getName()));
      } else {
        return new NameConflictException(
            String.format(
                "output file '%s' of rule '%s' conflicts with output file '%s' of rule '%s'",
                added.getName(),
                added.getGeneratingRule().getName(),
                existing.getName(),
                existing.getGeneratingRule().getName()));
      }
    }

    /** Utility function for generating exception messages. */
    private static String conflictsWith(Target target) {
      String message = "conflicts with existing ";
      if (target instanceof OutputFile) {
        message +=
            "generated file from rule '"
                + ((OutputFile) target).getGeneratingRule().getName()
                + "'";
      } else {
        message += target.getTargetKind();
      }
      return message + ", defined at " + target.getLocation();
    }

    @Nullable
    public Semaphore getCpuBoundSemaphore() {
      return cpuBoundSemaphore;
    }
  }

  /**
   * A collection of data about a package that does not require evaluating the whole package.
   *
   * <p>In particular, this does not contain any target information. It does contain data known
   * prior to BUILD file evaluation, data mutated by BUILD file evaluation, and data computed
   * immediately after BUILD file evaluation.
   *
   * <p>This object is supplied to symbolic macro expansion.
   */
  public static final class Metadata {

    private Metadata() {}

    // Fields that are known before the beginning of BUILD file execution

    private PackageIdentifier packageIdentifier;

    /**
     * Returns the package identifier for this package.
     *
     * <p>This is a suffix of {@code getFilename().getParentDirectory()}.
     */
    public PackageIdentifier getPackageIdentifier() {
      return packageIdentifier;
    }

    /**
     * Returns the name of this package. If this build is using external repositories then this name
     * may not be unique!
     */
    public String getName() {
      return packageIdentifier.getPackageFragment().getPathString();
    }

    /** Like {@link #getName}, but has type {@code PathFragment}. */
    public PathFragment getNameFragment() {
      return packageIdentifier.getPackageFragment();
    }

    private RootedPath filename;

    /** Returns the filename of this package's BUILD file. */
    public RootedPath getFilename() {
      return filename;
    }

    private Path packageDirectory;

    /**
     * Returns the directory in which this package's BUILD file resides. All InputFile members of
     * the packages are located relative to this directory.
     */
    public Path getPackageDirectory() {
      return packageDirectory;
    }

    private Label buildFileLabel;

    /** Returns the label of this package's BUILD file. */
    public Label getBuildFileLabel() {
      return buildFileLabel;
    }

    private String workspaceName;

    /**
     * Returns the name of the workspace this package is in. Used as a prefix for the runfiles
     * directory. This can be set in the WORKSPACE file. This must be a valid target name.
     */
    public String getWorkspaceName() {
      return workspaceName;
    }

    private RepositoryMapping repositoryMapping;

    /**
     * Returns the map of repository reassignments for BUILD packages. This will be empty for
     * packages within the main workspace.
     */
    public RepositoryMapping getRepositoryMapping() {
      return repositoryMapping;
    }

    /**
     * The name of the Bzlmod module associated with the repo this package is in. If this package is
     * not from a Bzlmod repo, this is empty. For repos generated by module extensions, this is the
     * name of the module hosting the extension.
     */
    private Optional<String> associatedModuleName;

    /**
     * The version of the Bzlmod module associated with the repo this package is in. If this package
     * is not from a Bzlmod repo, this is empty. For repos generated by module extensions, this is
     * the version of the module hosting the extension.
     */
    private Optional<String> associatedModuleVersion;

    private ConfigSettingVisibilityPolicy configSettingVisibilityPolicy;

    /** Returns the visibility policy. */
    public ConfigSettingVisibilityPolicy getConfigSettingVisibilityPolicy() {
      return configSettingVisibilityPolicy;
    }

    // These two fields are mutually exclusive. Which one is set depends on
    // PackageSettings#precomputeTransitiveLoads.
    @Nullable private ImmutableList<Module> directLoads;
    @Nullable private ImmutableList<Label> transitiveLoads;

    /** Governs the error message behavior of {@link Package#getTarget}. */
    // TODO(bazel-team): Arguably, this could be replaced by a boolean param to getTarget(), or some
    // separate action taken by the caller. But there's a lot of call sites that would need
    // updating.
    private boolean succinctTargetNotFoundErrors;

    // Fields that are updated during BUILD file execution.

    private PackageArgs packageArgs = PackageArgs.DEFAULT;

    /**
     * Returns the collection of package-level attributes set by the {@code package()} callable and
     * similar methods. May be modified during BUILD file execution.
     */
    public PackageArgs getPackageArgs() {
      return packageArgs;
    }

    // Fields that are only set after BUILD file execution (but before symbolic macro expansion).

    private InputFile buildFile;

    /**
     * Returns the InputFile target corresponding to this package's BUILD file.
     *
     * <p>This may change during BUILD file execution as a result of exports_files changing the
     * BUILD file's visibility.
     */
    public InputFile getBuildFile() {
      return buildFile;
    }

    private Optional<Root> sourceRoot;

    /**
     * Returns the root of the source tree in which this package was found. It is an invariant that
     * {@code sourceRoot.getRelative(packageId.getSourceRoot()).equals(packageDirectory)}. Returns
     * {@link Optional#empty} if this {@link Package} is derived from a WORKSPACE file.
     */
    public Optional<Root> getSourceRoot() {
      return sourceRoot;
    }

    private ImmutableMap<String, String> makeEnv;

    /**
     * Returns the "Make" environment of this package, containing package-local definitions of
     * "Make" variables.
     */
    public ImmutableMap<String, String> getMakeEnvironment() {
      return makeEnv;
    }
  }

  /** Package codec implementation. */
  @VisibleForTesting
  static final class PackageCodec implements ObjectCodec<Package> {
    @Override
    public Class<Package> getEncodedClass() {
      return Package.class;
    }

    @Override
    public void serialize(SerializationContext context, Package input, CodedOutputStream codedOut)
        throws IOException, SerializationException {
      context.checkClassExplicitlyAllowed(Package.class, input);
      PackageCodecDependencies codecDeps = context.getDependency(PackageCodecDependencies.class);
      codecDeps.getPackageSerializer().serialize(context, input, codedOut);
    }

    @Override
    public Package deserialize(DeserializationContext context, CodedInputStream codedIn)
        throws SerializationException, IOException {
      PackageCodecDependencies codecDeps = context.getDependency(PackageCodecDependencies.class);
      return codecDeps.getPackageSerializer().deserialize(context, codedIn);
    }
  }
}
