P.2.3 Core vs Rulesets

Bazel is a split system: a generic core understands dependency graphs, actions, caching, sandboxing, and execution, while rulesets teach that core how to build a particular language or workflow. That split makes the polyglot promise from P.1.1 Key Benefits concrete: the engine stays the same while the language support changes.1,2

How does Bazel learn to build a language?
Rulesets provide ecosystem knowledge. Bazel Core provides the shared build engine.
1 · RULESET
Supplies language-specific rules
Rule symbols and attributesrust_binary, srcs, deps
Tool integrationhow compiler actions are created
Ecosystem conventionspackages, IDEs, and generated code
2 · BUILD DECLARATION
Your repository loads and calls the rule
load("@rules_rust//rust:defs.bzl",
     "rust_binary")

rust_binary(
  name = "app",
  srcs = ["main.rs"],
)
During analysis, the rule registers the actions needed for this target.
3 · BAZEL CORE
Runs the language-neutral mechanics
Graph and analysisconnect targets, inputs, and actions
Scheduling and cachereuse results and order needed work
Sandbox and executionrun registered actions in controlled environments
Java rules Python rules Rust rules custom rules
Change the ruleset to change language knowledge. Keep the same graph, cache, scheduler, and CLI.

What belongs to Bazel Core

The core owns build mechanics, not language semantics. In Bazel's artifact model, engineers declare what artifact they want and its dependencies. Bazel decides how to schedule the work, which actions can run in parallel, and which previous results can be reused safely.3 When a rule is implemented in Starlark, its implementation function still does not run the compiler directly during analysis. It registers actions, and the core executes those actions later only if their outputs are needed.2,4

That is why the same engine can support very different ecosystems. The core does not need special built-in knowledge for every compiler, package manager, or framework. It needs a stable model for targets, inputs, outputs, and actions.2,4

What rulesets add

Rulesets supply the language- or domain-specific part: rule symbols, attributes, tool integrations, and conventions. The natively shipped rules are only a small amount of core support. Starlark-defined rules are how Bazel adds support for languages and tools it does not ship natively.2 In practice, a good ruleset is more than a parser for srcs and deps: it also has to fit the expectations of a language community, including package-manager integration, IDE support, and toolchain configuration.1

This layer is broader than programming languages. The same extension model can also add package-manager bridges, code generators, linting, and other workflows that the core intentionally does not hardcode.1,2

Why this gives you one mental model

Once you see the split, the uniform CLI makes more sense. bazel build, bazel test, and dependency edges stay the same whether the repository contains Java, Go, Python, Rust, or a mixture of all of them.1,3 If a language is not supported out of the box, the answer is usually not to wait for core Bazel. You add or adopt a ruleset.1,2

For most users, this means you rarely need to think about the boundary day to day. You mostly consume rule symbols in BUILD files. Level 0 makes that concrete in 0.3.2 Rules and 0.3.5 Load Statements. Much later, 4.2 Custom Rules, Providers & Actions explains how to author new rules, while 4.6 Toolchains & Platform Resolution shows how rules declare the toolchains and execution constraints they need.

key takeaway

If Bazel feels like one tool for many languages, that is because the core is intentionally generic and the language knowledge lives in rulesets. Learn to read the rule surface first. The deeper mechanics of custom rules and toolchains can wait until later levels.

extra

Why the boundary keeps getting sharper

Bazel is still moving more language behavior out of its historical Java core and into Starlark rules. For beginners, the resulting boundary is a smaller core and more independent rulesets.2 The same trend already shows up in migration guidance, where formerly builtin Java symbols such as java_common and JavaInfo move into rules_java, so extensions load them from rules packages rather than from the core binary.5

That detail matters more to rule authors than to beginners, but it reinforces the mental model: the smaller and more stable the core interface becomes, the easier it is for rulesets to evolve independently.2,5

Check your understanding · 3 questions

1.Match each layer of Bazel to what it is responsible for:

Drag each answer onto the matching prompt, or click an answer and then click a prompt

Answers
Bazel Core
Rulesets

2.Your language is not supported by Bazel out of the box. What is the usual answer?

Select one answer

3.True or false: what belongs to Bazel Core and what belongs to rulesets.

Choose True or False for each sentence

Adding support for another language normally means adopting or creating a ruleset, not teaching Bazel Core that compiler.
The core needs a stable model of targets, inputs, outputs, and actions — not built-in knowledge of every compiler.
Bazel is steadily moving language behavior out of its historical Java core into Starlark rules.
0 of 3 answered

Footnotes

  1. Bazel Vision — abstraction layer, multi-language support, and what a good ruleset must provide 1 2 3 4 5

  2. Rules — native rules as core support, Starlark rules for languages and tools, and rule implementations registering actions during analysis 1 2 3 4 5 6 7 8

  3. Artifact-Based Build Systems — Bazel controls the how, schedules work from the dependency graph, and reuses results safely 1 2

  4. Extension Overview — loading, analysis, and execution phases, plus rules as the place where new language support is introduced 1 2

  5. Migrating to Bazel Modules (a.k.a. Bzlmod) - Maintaining Compatibility, Part 1 — formerly builtin Java symbols moving into rules_java packages 1 2