[bldr]docs
Concepts

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 target

You 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.

FilterSelects
sitethat 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.

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/binary

selects two targets, not one:

bldr/cli/binary              the executable
bldr/cli/binary/diagnostics  what the compiler said about the code

You 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.

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> --defaults

The 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.

On this page