P.2 How Bazel Thinks

The first BUILD file can look like extra work: rule names, lists of sources, labels, and a tool that asks you to describe the build before it runs anything. This section explains why Bazel wants that structure.

P.2.1 Task-Based vs Artifact-Based gives the organizing idea. Many build tools organize tasks or commands. Bazel organizes targets, inputs, outputs, and dependency edges. Once Bazel knows that structure, it can decide what to build, what to skip, and what can be reused.

Targets, Not Tasks

Read this section as one sequence: first the model, then its consequences, then how rulesets extend Bazel, then the names for the behavior you see.

P.2.1 Task-Based vs Artifact-Based explains the central contrast. Bazel is not mainly asking "which task should run next?" It is asking "which target should be produced from which declared inputs and dependencies?"

P.2.2 Consequences of Artifact-Based explains what this changes in practice: cacheable outputs, remote sharing, graph pruning, and why frequent clean commands usually mean something is wrong.

P.2.3 Core vs Rulesets explains the split between Bazel Core and rulesets. Bazel Core is the engine. Rulesets teach it languages, tools, and ecosystems.

P.2.4 Five Properties gives names to the behavior Bazel is trying to provide: laziness, slicing, hermeticity, incrementality, and parallelism.

What The Structure Gives Bazel

The lesson is that Bazel needs declarations so it can reason about work. If Bazel knows the targets, inputs, tools, outputs, and dependencies, it can keep a build narrow, reuse previous outputs, and run independent work in parallel.

That also explains why Bazel can feel strict. A script can hide decisions inside code. Bazel asks you to move many of those decisions into BUILD files and rulesets. The trade is less hidden behavior in exchange for stronger guarantees.

Three Questions To Keep Asking

Once the target model is familiar, three plain questions help when a build does something surprising:

  1. What should this target depend on? Missing or hidden inputs can make a result unreliable. 2.3 Hermeticity & Sandboxing develops this question.
  2. Where did the work run? A local machine and a CI or remote machine may provide different conditions. 2.5 Execution Strategies explains the ways Bazel can run work.
  3. What did Bazel actually do? Check what was reused or rerun before choosing an explanation. 2.4 Caching & Incrementality starts that evidence habit.

For example, if CI produces a different result from your laptop, the first two questions suggest possible causes. The third keeps you from guessing. Use these questions to work through Prelude without memorizing new machinery.

Common Beginner Confusions

Readers coming from Maven, Gradle, Make, or language-native tools often expect the build file to be a workflow recipe. Bazel's BUILD files are closer to artifact declarations. That is why "just run this command" often becomes "describe the target, inputs, tools, and dependency edge first."

Another common habit is using clean whenever something looks wrong. P.2.2 Consequences of Artifact-Based explains why Bazel treats that as suspicious: if cleaning is required for correctness, the deeper problem is usually hidden inputs, non-hermetic tools, or broken trust in the cache.

key takeaway

Bazel thinks in declared targets, not opaque tasks. Declared inputs and dependency edges let it keep work narrow, reuse results, and run independent work safely. When behavior surprises you, ask what the target depends on, where the work ran, and what Bazel actually did.