// Copyright 2014 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.devtools.build.lib.analysis;

import com.google.devtools.build.lib.actions.ActionConflictException;
import com.google.devtools.build.lib.analysis.config.BuildConfigurationValue;
import com.google.devtools.build.lib.packages.AttributeMap;
import com.google.devtools.build.lib.packages.RuleClass;
import com.google.devtools.build.lib.skyframe.config.BuildConfigurationKey;

/**
 * A shortcut class to the appropriate specialization of {@code RuleClass.ConfiguredTargetFactory}.
 *
 * <p>Here follows an overview of how loading and analysis works in Bazel:
 *
 * <p>Actions (i.e. commands that are run during the build) are created by configured targets (see
 * {@link ConfiguredTarget}), which are a pair of a {@link
 * com.google.devtools.build.lib.cmdline.Label} (e.g. <code>//src:bazel</code>) and a {@link
 * BuildConfigurationKey}, which is a key for a {@link BuildConfigurationValue}, which is a blob of
 * data that contains extra information about how the target should be built (for example, for which
 * platform or with which C++ preprocessor definitions). Accordingly, a target can give rise to
 * multiple configured targets, for example, if it needs to be built both for the exec and the
 * target configuration.
 *
 * <p>The process of creating the appropriate {@link com.google.devtools.build.lib.actions.Action}s
 * for a configured target is called "analysis". The analysis of a configured target is composed of
 * the following steps (which process is orchestrated by {@link
 * com.google.devtools.build.lib.skyframe.ConfiguredTargetFunction}):
 *
 * <ol>
 *   <li>The corresponding {@link com.google.devtools.build.lib.packages.Target} is loaded, i.e. the
 *       BUILD file is parsed.
 *   <li>Its direct dependencies are analyzed, during which in turn indirect dependencies are also
 *       analyzed.
 *   <li>Aspects specified by the configured target are analyzed. These can be thought of as
 *       visitations of the transitive dependencies of the target. For more information, see {@link
 *       com.google.devtools.build.lib.packages.AspectClass}.
 *   <li>The configured target and the actions it generates are created based on the data from the
 *       previous two steps.
 * </ol>
 *
 * Targets can be of three main kinds (plus a few special ones which are not important for
 * understanding the big picture):
 *
 * <p>
 * <li>Input and output files. These represent either a file that is in the source tree or a file
 *     produced by during the build. Not every file produced during the build has a corresponding
 *     output file target.
 * <li>Rules. These describe things a build actually does. Each rule has a class (e.g. <code>
 *     cc_binary</code>). Rule classes can be defined either in Starlark using the <code>rule()
 *     </code> function or in Java code by implementing {@link
 *     com.google.devtools.build.lib.analysis.RuleDefinition}.
 *
 *     <p>During the analysis of a configured target, the following pieces of data are available:
 *
 *     <ul>
 *       <li>The corresponding target itself. This is necessary so that the analysis has access to
 *           e.g. the attributes a rule has in the BUILD file.
 *       <li>The {@link com.google.devtools.build.lib.analysis.TransitiveInfoCollection}s of direct
 *           dependencies. They are used to gather information from the transitive closure, for
 *           example, the include path entries for C++ compilation or all the object files that need
 *           to be compiled into a C++ binary.
 *       <li>The configuration, which is used to determine which compiler to use and to get access
 *           to some command line options of Bazel that influence analysis.
 *       <li>Skyframe, for requesting arbitrary Skyframe nodes. This is an escape hatch that should
 *           be used when other mechanisms provided are not suitable and allows one to e.g. read
 *           arbitrary files. With great power...
 *     </ul>
 *
 *     <p>Analysis of non-rule configured targets is special-cased and is not covered here.
 *
 *     <p>The analysis of a rule itself is done by implementations {@link
 *     RuleConfiguredTargetFactory} (there should be one for each rule class). The data above is
 *     available using the {@link RuleContext} argument passed into its create() method. It should
 *     result in three things:
 *
 *     <ul>
 *       <li>A set of actions. These should be passed to {@link RuleContext#registerAction},
 *           although for more common cases (e.g. {@link
 *           com.google.devtools.build.lib.analysis.actions.SpawnAction}), shortcuts are provided.
 *       <li>A set of artifacts (files produced by actions). These should be created using methods
 *           of {@link RuleContext}. Each artifact thus created must have a generating action.
 *       <li>A set of {@link com.google.devtools.build.lib.analysis.TransitiveInfoProvider}s that
 *           are passed on to direct dependencies. These must be registered using {@link
 *           com.google.devtools.build.lib.analysis.RuleConfiguredTargetBuilder#add( Class,
 *           com.google.devtools.build.lib.analysis.TransitiveInfoProvider)}
 *     </ul>
 *
 *     <p>Configured targets are currently allowed to create artifacts at any exec path. It would be
 *     better if they could be constrained to a subtree based on the label of the configured target,
 *     but this is currently not feasible because multiple rules violate this constraint and the
 *     output format is part of its interface.
 *
 *     <p>In principle, multiple configured targets should not create actions with conflicting
 *     outputs. There are still a few exceptions to this rule that are slated to be eventually
 *     removed, we have provisions to handle this case (Action instances that share at least one
 *     output file are required to be exactly the same), but this does put some pressure on the
 *     design and we are eventually planning to eliminate this option.
 *
 *     <p>These restrictions together make it possible to:
 *
 *     <ul>
 *       <li>Correctly cache the analysis phase; by tightly constraining what a configured target is
 *           allowed to access and what it is not, we can know when it needs to invalidate a
 *           particular one and when it can reuse an already existing one.
 *       <li>Serialize / deserialize individual configured targets at will, making it possible for
 *           example to swap out part of the analysis state if there is memory pressure or to move
 *           them in persistent storage so that the state can be reconstructed at a different time
 *           or in a different process. The stretch goal is to eventually facilitate cross-user
 *           caching of this information.
 *     </ul>
 */
public interface RuleConfiguredTargetFactory
    extends RuleClass.ConfiguredTargetFactory<
        ConfiguredTarget, RuleContext, ActionConflictException> {

  /** Adds any rule implementation-specific requirements to the given builder. */
  default void addRuleImplSpecificRequiredConfigFragments(
      RequiredConfigFragmentsProvider.Builder requiredFragments,
      AttributeMap attributes,
      BuildConfigurationValue configuration) {}
}
