“Efficient Starlark coding begins with an understanding of its operational semantics and how they interact with Bazel’s build system.”
The Build Process in Skyframe
Skyframe is Bazel’s incremental computation framework that enables continuous analysis and execution. It manages dependencies and efficiently determines what work needs to be done.
Skyframe divides the Bazel build process into two main phases:
- Analysis Phase
- Execution Phase
1. Target Pattern Parsing
When you run a command like bazel build //foo:all, Bazel first parses the target pattern to determine the set of build targets. This outputs the TargetPatternParsingResult.
2. Analysis Phase
Bazel evaluates ActionLookupKeys to produce ActionLookupValues:
- ActionLookupKeys: Represent the targets (e.g.,
//foo:a,//foo:c) that Bazel needs to analyze. - ActionLookupValues: Contain the actions (like compile or link) required to build these targets.
This builds an AnalysisResult that describes what needs to be executed.
3. Execution Phase
Bazel evaluates CompletionKeys to produce CompletionValues:
- CompletionKeys: Represent the inputs needed to execute the actions defined in the analysis phase.
- CompletionValues: Contain the results of executing these actions.
How Skyframe Makes Bazel Efficient
- If a source file has not changed, Bazel skips re-analyzing or re-executing actions.
- Skyframe tracks dependencies and knows exactly which parts of the build graph need updates.
Key Takeaways
- Analysis Phase: Transforms build targets into actionable tasks (ActionLookupKeys -> ActionLookupValues).
- Execution Phase: Executes tasks to generate outputs (CompletionKeys -> CompletionValues).
- Efficiency: Skyframe’s incremental computation ensures Bazel only does the necessary work.