2.2 Three Phases of a Build
Run bazel build //app:server and a line like this appears before the command
finishes:
INFO: Analyzed target //app:server (14 packages loaded, 48 targets configured).
That summary reports loading and analysis work. Before ordinary tools produce outputs, Bazel reads declarations and turns reachable targets into an action plan. Execution then runs the needed actions that are not already satisfied by cache hits.
The target graph from 2.1 Directed Acyclic Graph (DAG) is therefore only the first layer. A target graph is not yet an action graph, and an action graph is not yet executed work. The phase model separates those layers so the log can tell you which responsibility produced a symptom.
Read The Boundary As Evidence
Start with 2.2.1 Loading, Analysis & Execution if loading and analysis still seem
interchangeable. It assigns each phase a responsibility and gives you the
mnemonic package -> target -> action -> artifact.
2.2.2 Reading Build Output applies that vocabulary to a failing command. In a
simple phase-separated trace, a failure before INFO: Analyzed ... points
toward packages, labels, BUILD or .bzl files, dependency declarations, or
rule validation. A failure after it points toward execution, including
compilers, linkers, tests, sandboxes, and tools producing outputs. Treat the
line as a clue rather than a hard boundary because Skymeld may execute ready
actions while analysis of the wider request continues.
The counters need the same phase context. packages loaded describes the
requested package slice, not compilation. targets configured describes
analysis work, not commands that ran. total actions is not a count of commands
executed from scratch because cache hits, null builds, and already-valid outputs
affect it.
The Plan Exists Before Tools Run
2.2.3 Static Action Graph explains why ordinary rules register actions,
inputs, and outputs during analysis instead of compiling first and discovering
the rest of the build later. That up-front plan makes bazel aquery, cache
keys, parallel scheduling, and remote execution possible. Read it when a rule
or language integration runs into Bazel's plan-first boundary.
2.2.4 Skymeld adds the scheduling caveat. Modern Bazel may overlap analysis and execution, especially when some top-level targets finish analysis before others. The responsibilities remain distinct even when their timing overlaps. This article is optional unless you are comparing timings or reading profiles.
The distinction also explains why bazel query can inspect the target graph
without compiling anything and bazel aquery can show the planned actions
without running them. Visibility or dependency-graph failures can stop the
build on the declaration side, while sandbox failures concern an executing
action's view of its inputs.
The eager-fetch-load-edge snippet makes a loading edge visible: its BUILD file loads an external helper, which buildfiles(deps(...)) reveals even though target deps() does not.
This phase boundary supports the action-focused models in 2.3 Hermeticity & Sandboxing, 2.4 Caching & Incrementality, and 2.5 Execution Strategies. Each asks a different question after Bazel has established what work the request means.
Loading discovers packages, analysis turns reachable targets into an action plan, and execution runs the needed actions. Even when Bazel overlaps that work, classifying a symptom by responsibility tells you which logs and debugging tools can explain it.
Sections in this chapter · 4
Loading declarations, analyzing configured targets into actions, and executing the uncached work.
Reading analysis milestones and counters to locate a failure or unexpected amount of graph work.
Why ordinary rules must declare actions, inputs, and outputs during analysis before tools execute.
How Skymeld overlaps ready execution with ongoing analysis without changing phase responsibilities.