.rbs-language API you use. A rule is defined with native.define_rule(),
usually in a module that build files load().
native.define_rule()
load().
For
kind = "binary" and "library" the target’s output is its directory
under .rbs/bin/<platform>/<package>/<name> — the same tree ctx.bin
points at — so caching and rbs run work without per-rule wiring.
The attr module
attr.* constructors describe a rule’s attributes inside attrs = {...}.
Shared parameters (all optional, all keyword):
How targets instantiate
When a build file calls your rule:nameis required, andsrcs/depsget first-class handling (depsbecome graph edges; entries starting with@external://are filtered out of the graph and left for the implementation to resolve).- Any attribute declared with
is_dep = Truealso contributes:nameand//pkg:namelabels as graph edges. envandtarget_compatible_withare accepted by every rule automatically.- All keyword arguments — declared or not — are recorded on the target and
visible to the implementation as
ctx.attr.<key>.
The implementation function
The implementation receives one argument,ctx, and runs at build
time (not while the build file loads), only when the target is requested
and its action cache key misses.
Read optional attributes defensively —
hasattr(ctx.attr, "srcs") — since
an attribute the caller never set may be absent from ctx.attr.The ctx API
Identity and attributes
Output paths: ctx.bin
ctx.bin is the hermetic, package-isolated output layout for the current
target — the recommended place for everything the target produces:
Source paths: ctx.src
ctx.actions
ctx.file
ctx.dir
ctx.json, ctx.archive, ctx.http
Tools and toolchains
External dependencies
Text and HTML helpers
Specialized modules
Outputs and caching
- For
kind = "binary"/"library", the target’s recorded output is itsctx.binoutput directory; the action cache stores and restores that tree, andrbs runfinds the executable there. ctx.file.read,ctx.file.copy,ctx.file.copy_treeandctx.dir.link_entriesregister what they touch as cache inputs, so editing a source file invalidates the target even though your implementation is a build-language function rather than a command line.- Treat staged trees (runfiles,
node_modules, dist bundles) as derived state:ctx.dir.removethen rebuild, or deleted sources live on in the old tree and keep getting compiled.
Sharing data between rules
rbs has no Bazel-style provider objects. The convention — used by the embedded language rules — is to write a metadata file into the target’s output directory and have dependents read it:Legacy form: outputs + actions
Instead ofimplementation, a rule may declare two functions evaluated at
load time:
name, command (argv list) or fn (a
build-language callable), inputs, outputs, working_dir, description,
mnemonic, toolchain. Prefer implementation for new rules.
Testing rules
Unit tests: rbs rules test
assert functions: