Targets
What a workspace can produce, and how a build picks among those things.
A target is one thing your workspace can produce: a directory of files, a container image, a test suite, something runnable, something deployable. Your build code declares them. A build picks which ones to actually produce.
Those are two separate questions, and keeping them separate is the point. A workspace declares everything it could build once. Each build says which of those it wants right now.
Targets have names
A target's name is where it was declared: the member, the scopes inside it, and the name it was given.
bldr/daemon/tests/unit
└────┬────┘ └─┬─┘ └┬─┘
member scopes the targetYou see these names everywhere: in bldr builds get, in the console, and in
every filter. Nothing else identifies a target, which matters because two
members can both declare test and only the full name tells them apart.
A target declared under another one's name is its companion — see Companions come along.
Choosing with filters
A build's selection is a list of filters, and it produces the union of all of them. Filters only ever add.
| Filter | Selects |
|---|---|
site | that one target, if it exists |
bldr/daemon/** | bldr/daemon and everything inside it |
bldr/* | everything in every bldr/<something> |
**[test] | every test target in the workspace |
bldr/ui/**[image] | only the container images under bldr/ui |
**/lsp[bldr.runnable.lsp=v1] | by label |
A pattern with no * means exactly that one target. bldr/daemon is the
target called bldr/daemon, not the things inside it. Write /** for the
subtree.
Typing a member name on the command line does the obvious thing:
bldr build bldr/daemon is shorthand for bldr/daemon/**. The exactness
matters when you write a filter into the workspace file, where a name that
quietly meant its whole subtree would be a trap.
Quote your patterns. bldr build bldr/* lets the shell expand * against your
local files first, and bldr never sees what you typed.
Kinds
The bracket narrows to a kind: directory, image, test, runnable,
deployment, coverage, metrics, diagnostics. Several constraints in one
bracket must all hold.
Companions come along
Some targets are incomplete on their own. Compiling a binary also produces everything the compiler said about your code — but the findings live in a separate target, so a build that selected only the binary would produce them and throw them away.
A target can therefore declare peers: other targets that are selected whenever it is.
bldr build bldr/cli/binaryselects two targets, not one:
bldr/cli/binary the executable
bldr/cli/binary/diagnostics what the compiler said about the codeYou never name the second one. Every cargo command that runs the compiler
declares its diagnostics companion this way, and every test target declares
its metrics companion — the summary row bldr builds metrics charts.
Companions are named as a path under their base (<target>/diagnostics), so a
subtree filter picks them up for the same reason bldr/daemon/** picks up
everything under bldr/daemon.
Peers are not dependencies. Nothing is ordered by them and nothing forces them to succeed: a target whose peer fails still succeeds, and a peer that fails fails alone. They only widen what a filter selected. Peers are followed through chains, so a companion may have one of its own.
This is why a build that fails to compile still has diagnostics. The compile
records its findings and its exit status separately; only the artifacts that
needed the compile to work fail with it. bldr builds problems <BUILD-ID> on a
red build shows the errors, not just "the build failed".
Changing the selection mid-build
You do not have to start over.
bldr builds set-targets <BUILD-ID> '**[test]'
bldr builds set-targets <BUILD-ID> --defaultsThe build resumes under the new selection. A running build stops what it had in flight; a finished or failed one starts again. That second case is the useful one: if a build failed on a target you do not need right now, drop it and the build can go green without re-running anything else. Everything already built is cached by content, so a resumed build re-reaches its finished targets immediately.
Reading the result
Every target the workspace declares is listed, whether or not this build selected it, so the list doubles as the answer to "what else could I build here". A filter that matches nothing says so, marked not found, rather than quietly producing an empty build.
Narrowing the selection does not skip reading your build code. Every member is still loaded, which is how the unselected list stays complete and how a type error anywhere still surfaces. What narrowing skips is the work.