Bazel Developer Activities and .bzl Training Guide#
This guide maps common OpenROAD developer activities to Bazel workflows and provides practical training steps for reading and maintaining .bzl (Starlark) files.
It is intended for contributors who already build and test OpenROAD, and want to become productive with Bazel internals and review-ready changes.
Scope#
This document covers:
day-to-day developer activities
where to find relevant Bazel logic in the repository
how to approach
.bzland Starlark changes safelyminimal commands to verify changes locally before opening a PR
For general Bazel usage (running tests, build configs, caching, ORFS details), see:
Repository areas to know#
You will work mostly in:
BUILD.bazel/BUILDfiles: target declarationsMODULE.bazelandMODULE.bazel.lock: dependency/module management.bazelrc: shared Bazel flags and configsbazel/*.bzl: shared Starlark macros and helpers used across targetstest/regression.bzlandtest/orfs/**/*.bzl: regression and ORFS-related Starlark logic
Treat .bzl files as code: keep changes small, reviewable, and tested.
Activity matrix (what developers do most often)#
1) Modify C++/Tcl/Python code and run fast local checks#
Typical flow:
make code change
run focused tests in affected subtree
run broader checks before PR
Examples:
bazelisk test //src/<tool>/...
When broad integration confidence is needed:
bazelisk test //...
Use narrow scope first; widen only as confidence increases.
2) Add or update a target in a BUILD file#
Common tasks:
add a new test target
add data dependencies
split/reuse libraries for better build graph hygiene
Recommended process:
copy a nearby target pattern
keep visibility minimal
avoid over-exporting internals
run only the new/changed target first
then run subtree tests
Example validation steps:
bazelisk query 'kind(test, //src/<tool>/...)'
bazelisk test //src/<tool>/test:<new_test_target>
The test target name is derived from the test file name with a suffix added
based on type: Tcl tests get _tcl and Python tests get _py. For example,
src/grt/test/fastroute.tcl becomes target fastroute_tcl, so you would run:
bazelisk test //src/grt/test:fastroute_tcl
Use the bazelisk query command above to list all test targets and find the
exact name for any test in the subtree.
4) Update ORFS/Bazel-ORFS coupling#
If your change touches integration boundaries:
verify OpenROAD side and ORFS assumptions together
use the documented ORFS debug/issue-generation workflow in
test/orfs/README.mdrun at least affected ORFS smoke tests before PR
5) Update Bazel module/dependency state#
When bumping module inputs:
prefer project-documented bump flow
review both
MODULE.bazeland lock updateskeep diffs minimal and intentional
verify representative build/tests after update
.bzl training path (practical, repo-oriented)#
Step 1: Read Starlark with intent#
When reading a .bzl file, identify:
exported symbols (macros/rules) used by
BUILDfilesinputs (attrs/kwargs) and defaults
what target(s) the macro expands into
implicit outputs, tags, and toolchain assumptions
Focus first on call sites in nearby BUILD files.
Step 2: Learn by tracing one macro end-to-end#
Pick one macro used in your area and trace:
BUILDcall sitemacro parameters and normalization
final native rules emitted
resulting target graph via query
This builds intuition faster than reading Starlark in isolation.
Step 3: Make no-op/refactor-safe edits first#
Before behavior changes, practice with small, review-safe edits:
variable naming cleanup
comments clarifying non-obvious behavior
extracting small helper functions without semantic changes
Then run representative tests. This gives confidence in your local loop and reduces risk.
Step 4: Introduce behavior changes behind clear conditions#
For real logic changes:
keep old path available when practical
gate new behavior with explicit kwargs or clear branch conditions
avoid hidden behavior changes to unrelated consumers
Step 5: Validate like a maintainer#
For .bzl changes, do not stop at one passing target.
Validate across:
direct consumer(s)
at least one unrelated consumer
broader subtree or project-level tests proportional to blast radius
Code review checklist for Bazel / .bzl changes#
Before opening a PR, verify:
change is minimal and scoped to one intent
BUILD/.bzlnaming is clear and consistent with nearby codeno accidental visibility broadening
test target selection matches changed area
representative tests passed locally
docs updated when behavior/workflow changed
For larger .bzl changes, include a short “impact summary” in PR description:
what changed
who consumes it
what was tested
Common pitfalls and how to avoid them#
Changing shared macros without representative tests
Always test more than one consumer.Overusing broad target patterns too early
Start narrow (//src/<tool>/...), then widen.Conflating host/target configs when debugging
Use guidance in Bazel targets and Bazel.md.Mixing unrelated cleanup with behavioral changes
Separate commits improve review quality and rollback safety.Unclear PR validation evidence
Include exact commands you ran and the scope they cover.
Suggested onboarding exercises for new developers#
These are low-risk training tasks that build Bazel confidence:
run and list tests in a single tool subtree
add a tiny test target in a local branch and validate it
trace one
.bzlmacro from call site to emitted rulesmake a non-functional clarity edit in
.bzland confirm no regressionsdocument your local validation commands in PR style
Minimal verification template (copy/paste for PR notes)#
Use and adapt this in your PR description:
Scope:
- <what changed>
Validation:
- bazelisk test //src/<tool>/test:<specific_target>
- bazelisk test //src/<tool>/...
- bazelisk test //src/...
Notes:
- <any known limitations or follow-up work>
Keep validation proportional to change scope.
When to ask for help#
Ask early if:
you are unsure whether a
.bzlmacro is shared across many consumersa change requires module/toolchain decisions beyond local context
target/config behavior is surprising across
buildvstest
A short design note in the PR discussion is better than a large speculative change.
Summary#
For OpenROAD Bazel work, reliability comes from:
small scoped edits
understanding call site → macro → emitted rule flow
representative validation across consumers
explicit, reproducible test evidence in PRs
If you follow this workflow, your .bzl and Bazel changes are much more likely to be easy to review and safe to merge.