Skip to content

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.

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

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.tsx
A src/menu.tsx

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

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.

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.

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.

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.

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.