diff options
author | 2016-05-19 11:06:37 +0000 | |
---|---|---|
committer | 2016-05-19 16:28:06 +0000 | |
commit | 2300cd6ffecf9afcd7ac0704c47c3e6bc519f024 (patch) | |
tree | 364499b7923b59ee7c56fb436316c07837295df2 /src/main/java/com/google/devtools/build/lib/rules | |
parent | 941ef4d96d85e114eb6cca2fc0f646578ab0ef27 (diff) |
Add an overview comment about how the analysis phase works and some pointers to it.
--
MOS_MIGRATED_REVID=122718503
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/rules')
-rw-r--r-- | src/main/java/com/google/devtools/build/lib/rules/RuleConfiguredTargetFactory.java | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/rules/RuleConfiguredTargetFactory.java b/src/main/java/com/google/devtools/build/lib/rules/RuleConfiguredTargetFactory.java index dd846833ba..6f5eb7cd90 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/RuleConfiguredTargetFactory.java +++ b/src/main/java/com/google/devtools/build/lib/rules/RuleConfiguredTargetFactory.java @@ -13,12 +13,109 @@ // limitations under the License. package com.google.devtools.build.lib.rules; +import com.google.devtools.build.lib.actions.ActionAnalysisMetadata; import com.google.devtools.build.lib.analysis.ConfiguredTarget; import com.google.devtools.build.lib.analysis.RuleContext; import com.google.devtools.build.lib.packages.RuleClass; /** * 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}), wich are a pair of a target (e.g. <code>//src:bazel</code>) and a + * {@link com.google.devtools.build.lib.analysis.config.BuildConfiguration}, 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 host 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> + * <li>Its direct dependencies are analyzed, during which in turn indirect dependencies are + * also analyzed.</li> + * <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.</li> + * </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> + * <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 Skylark using the + * <code>rule()</code> function or in Java code by implementing + * {@link com.google.devtools.build.lib.analysis.RuleDefinition}.</li> + * </p> + * <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> + * <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> + * <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> + * <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(ActionAnalysisMetadata...)}, although for more + * common cases (e.g. {@link com.google.devtools.build.lib.analysis.actions.SpawnAction)}, + * shortcuts are provided.</li> + * <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> + * <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)} + * </li> + * </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> { |