Core targets and configuration
The target types, configuration properties, and flags that ship in fabr’s core (STD.fabr) and are
always available, independent of any language plugin. Ecosystem-specific definitions (like
js_package) come from plugins — see JavaScript targets and configuration,
Java targets and configuration, Container targets and
configuration and AWS targets and
configuration.
This page is generated from fabr list-all, so it never drifts from the code.
Global properties
Section titled “Global properties”| Property | Default | Description |
|---|---|---|
@fabr-build |
@fabr-home:@fabr-build |
Supply @fabr-build packages directly into the root namespace. |
ADVISORIES |
https://api.osv.dev |
The advisory database fabr audit checks packages against: the base URL of a server answering OSV’s API (https://google.github.io/osv.dev/api/), such as osv.dev or a mirror of it. |
BUILD_OPERATION |
build |
What is being done with a target: build (produce its output), test (run its tests), run (produce it as a program that can be launched) or files (its built output as plain files). The build, test and run commands set it; a build script can require it of a dependency (tool<BUILD_OPERATION=run>). |
BUILD_TYPE |
debug |
How far a build is optimised and how much debugging information it keeps: debug (not optimised, full debugging information), relwithdebinfo (optimised, debugging information kept) or release (optimised, debugging information removed). |
COVERAGE |
off |
Whether what is built and tested is measured for code coverage: on or off. fabr test --coverage sets on for one run. A tool is always built with it off. |
TARGET |
${HOST} |
The platform being built for, as a clang/LLVM target triple such as arm64-apple-macosx15.0 or x86_64-linux-gnu. Defaults to HOST, the machine fabr is running on. Set it to cross-compile: for a whole run with -DTARGET=…, or for one dependency with mylib<TARGET=…>. Platform-specific packages are selected by it. |
TEST_EXPECTATIONS |
check |
What a test run does when a result differs from the expectation recorded for it, such as a snapshot: check fails the test and reports the difference; update records the new result and, after a passing run, writes the changed records back into the source tree. fabr test -u sets update for one run. |
TEST_NAME_PATTERN |
(unset) |
The regular expression selecting the tests a test run runs: a test runs where it matches part of the test’s name as its runner names it, such as suite and test names joined by spaces, or Class#method. Empty runs every test. fabr test -t PATTERN sets it for one run. |
Targets
Section titled “Targets”catalog
Section titled “catalog”targetdef catalog { deps = PACKAGES;}A named set of dependencies whose versions are chosen once, together. Refer to
a member wherever a dependency is wanted as <catalog>:<package>, with no
version:
catalog @pkg { deps = @npm:react:^19.1.0 @npm:react-dom:^19.1.0; }
js_package ui { srcs = src:**/*.tsx; deps = @pkg:react @pkg:react-dom; }Every target that uses the catalog gets the same version of each member, and of everything the members depend on. A member is downloaded only when a target uses it.
| Property | Type | Required | Description |
|---|---|---|---|
deps |
PACKAGES | The members: packages from a registry, each with its version, or package targets of this project. |
generate
Section titled “generate”Operations: build
targetdef generate { srcs = FILES; run = REQUIRED COMMAND; output = STRING; incremental = STRING; changes = STRING; env = MAP;}Run a command and keep its output as the target’s files, for code generation or any step that no other target type covers:
generate api_docs { srcs = ./templates/**; run = list_api --json | render_docs > reference.md;}Each command in run is a runnable target or package, or a program on your
machine named through @host (@host:clang). The commands run in a directory
holding srcs.
The result is the files the redirections capture (> name). When output is
set, the result is instead the files it selects, from the captured files and
from anything the commands wrote.
A command can carry files over from one successful run to the next, so that a tool redoes only what changed:
generate styles { srcs = ./src/**; run = css_tool --state state.json --changes changes.txt -o styles.css; output = styles.css; incremental = state.json; changes = changes.txt;}The files incremental matches are put back under the same names before the
next run, and the file named by changes lists what changed in the inputs
since that run, one line per file: A, M or D (added, modified,
deleted), a tab, then the file’s name in the directory the commands run in:
M src/button.tsxA src/menu.tsxNeither is there for the first run, or after the cache has been cleared, and
the command must then do the whole job. Either way it must produce exactly
what it would from nothing, because fabr caches its result as if it had. A
file that both output and incremental match is part of the result and is
carried over too.
| Property | Type | Required | Description |
|---|---|---|---|
srcs |
FILES | Input files, placed in the directory the commands run in. | |
run |
REQUIRED COMMAND | yes | The command to run: a pipeline of runnables with their arguments, with |, <, >, 2> and &> as in a shell. |
output |
STRING | Which files to keep, as a pattern with an optional rename: dist:**, *.out -> *.txt. |
|
incremental |
STRING | Which files the command keeps for its next run, as a pattern like output’s: staged back under those names before it, once a run has succeeded. |
|
changes |
STRING | Where to write what changed in the inputs since the last successful run, one A|M|D<tab>name line per file; not written where there is no such run. |
|
env |
MAP | Environment variables for the commands, over each runnable’s own env: the commands run with no others. |
patched
Section titled “patched”Operations: build
targetdef patched { srcs = REQUIRED PACKAGES; patches = FILES; run = COMMAND; env = MAP; fixes = STRING;}Change a package, or plain files, with patches or a command:
patched glob-promise { srcs = @npm:glob-promise:1.33.0; patches = patches/glob.patch; }When srcs is one package, the result is a package with this target’s name
and the original’s version and dependencies. Naming the target after the
package therefore replaces that package wherever it is used. For anything
else, the result is the changed files.
| Property | Type | Required | Description |
|---|---|---|---|
srcs |
REQUIRED PACKAGES | yes | What to change. |
patches |
FILES | Unified diffs, applied in the order written, with paths as git writes them (a/lib/x.js). |
|
run |
COMMAND | A command run after the patches, in the directory holding the files, which it changes in place: a pipeline of runnables as generate’s run is. |
|
env |
MAP | Environment variables for the command, over each runnable’s own env: the command runs with no others. |
|
fixes |
STRING | The advisories the change fixes in the package srcs names, by id or alias (GHSA-…, CVE-…): fabr audit reports them as fixed here. |
Operations: build
targetdef zip { srcs = REQUIRED FILES;}A zip archive of files, named after the target (<name>.zip). A symlink among
them is stored as a symlink, and must link to a place within the archive.
| Property | Type | Required | Description |
|---|---|---|---|
srcs |
REQUIRED FILES | yes | The archive’s contents, named as they are found. |
script
Section titled “script”Operations: run
targetdef script { deps = FILES; entry = REQUIRED FILES; args = STRING;}A shell script that can be run: with fabr run, as a command in a generate
target, or as the tool of a serve target.
| Property | Type | Required | Description |
|---|---|---|---|
deps |
FILES | Other files the script needs, placed alongside it under their own names. | |
entry |
REQUIRED FILES | yes | The script file, which is run with sh. |
args |
STRING | Arguments passed to the script ahead of any given when it is run. |
Operations: run
targetdef serve { tool = REQUIRED FILES; deps = FILES; args = STRING; files = FILES; env = MAP;}A long-running program together with the files it serves, such as a development server:
serve site { tool = @npm:http-server:14.1.1; files = site_build; args = -c-1 .; }fabr run site starts the program in a directory containing files, so a
static file server needs no path argument. Under fabr run -w, a change to
files is copied into that directory while the program keeps running; a
change to tool, deps, args or env restarts it.
| Property | Type | Required | Description |
|---|---|---|---|
tool |
REQUIRED FILES | yes | The program to run: a script or js_script target, or a package that has a command-line program. |
deps |
FILES | Other files the program needs, placed in the directory it runs in. | |
args |
STRING | Arguments passed to the program ahead of any given to fabr run. |
|
files |
FILES | The content to serve. | |
env |
MAP | Environment variables added to those fabr run was started with. |
Operations: build
targetdef sync { * = FILES;}Publish built packages to a registry, or files to a store such as S3. Each
entry names where its content goes and which target supplies it; for an npm
registry that is <registry>:<name>:<version> = <target>;:
sync release { @npm:@acme/core:1.2.0 = @acme/core<BUILD_TYPE=release>; @npm:@acme/cli:1.2.0 = @acme/cli<BUILD_TYPE=release>;}An entry publishes the build type it is given, so <BUILD_TYPE=release> on
the target is what makes the published package a release build.
fabr build release produces the content as it would be published, without
uploading anything. fabr sync release uploads it, each package after the
packages it depends on. Where one entry depends on another, the published package
requires the version assigned to it here.
targetdef fetch { * = STRING;}A set of files to download, each with the integrity hash its contents must match:
fetch @dl { node.tar.gz = "https://nodejs.org/dist/v22.15.0/node-v22.15.0.tar.gz" "sha256-…"; }@dl:node.tar.gz is then the downloaded file, and @dl:node.tar.gz:*:bin/node
a file inside the archive. The hash is required, is written
<algorithm>-<base64>, and is checked on every download. A file is downloaded
only when something refers to it.
repository_group
Section titled “repository_group”targetdef repository_group { * = FILES;}Combine several registries into one, choosing the registry for each package by its name:
repository_group @deps { @acme/* = @internal; * = @npm;}Dependencies are then written @deps:<package>:<version>, and versions are
chosen across all the registries together. A key is a package name, a name
prefix ending in *, or * alone for everything else. The longest matching
key decides, whatever order the entries are written in. A package is looked up
only in the registry its name selects, never in another as a fallback. The
registries must all be of the same kind.
A value can instead be a target or files, to be used as the package of exactly that name.
fabr_home
Section titled “fabr_home”targetdef fabr_home {}The packages installed with fabr itself — its plugins and the tools they use —
at the versions installed. @fabr-home:@fabr-build/sass-pnp-importer is the
installed package, whatever the project declares.
host_searchpath
Section titled “host_searchpath”targetdef host_searchpath {}The programs on the search path of the machine fabr runs on, used where they
lie: @host:clang is the clang a shell would run, and @host:/usr/bin/cc
the program at that path. Each is identified by its content: a different
build of it is a different input.
Operations: *
targetdef flag { provides = FILES;}A named switch. A target turns a flag on by listing it in its deps, and the
rules that build the target decide what it means (dom, ts/no_strict).
Declare your own to give a set of flags one name:
flag legacy_ts { provides = ts/no_strict_null_checks ts/allow_implicit_any; }| Property | Type | Required | Description |
|---|---|---|---|
provides |
FILES | Other flags this one turns on. |