On this page
Building Rust with kompilator
Rust builds go through kompilator
Every Rust build Stado runs itself compiles with kompilator, never Cargo. Stado
carries kompilator's sources and compiles kompilator once per source digest
with the machine's own rustc. The carried sources are every file under
kompilator/src, listed by stado-product's build script as Stado builds, so
a file kompilator gains is carried by the next build of Stado without anyone
adding it to a list. kompilator keeps the units it compiled in a
store of its own and reuses them in the next build of the same sources, so no
compiler cache is installed or put in front of a compiler; the Kache cache and
its compiler-cache commands are gone. That covers:
- the owner-local
stado product installof akind: kompilatorrecipe, which runskompilator build --revision <commit> --release --bin …, keeps the checkout's units in its build area and places each binary from the path kompilator printed; the receipt'skompilatorfield names the program, its digest, the unit store and the paths answered, and Stado Desktop's Products screen shows it; stado product kompilator stage --bin NAME [--features A,B]on a release builder, a kompilator build that takes only--binand--features(stage builds with kompilator, which takes --bin NAME and --features A,B; remove …otherwise) and runs the kompilatorKOMPILATORnames when it is set (KOMPILATOR names <path>, and no kompilator is there…when nothing is there);- every step of a release builder job, which finds
kompilatorfirst onPATHwithKOMPILATORandKOMPILATOR_CACHE(its unit store for the product and platform under the build cache) set, and noCARGO_TARGET_DIRor compiler wrapper; its log says[release-worker] kompilator: <path> (<digest>); units kept at …. Every job the agent runs carriesKOMPILATOR_JOBS, the cores the job asked for, and kompilator compiles with that many jobs when no--jobsis given (a value that is not a positive whole number is refused naming the variable); stado quality checkandstado quality format, which run their gates and build with the kompilatorKOMPILATORnames when the caller set it, else the one compiled from the sources this Stado carries; so a check still runs when the carried sources do not compile, including the check of the change that repairs them, and a refusal sayscannot run kompilator for this check: the one KOMPILATOR names when it is set, else the one Stado compiles from the sources it carries into …;stado host upgradeandstado host kompilator … build, below.
kompilator is compiled into ~/.stado/products/kompilator/<digest>/kompilator
through a staging directory beside it, staging-<pid>-<uuid>, named by the
process compiling there and renamed into place once rustc succeeds, so no
build runs a half-written program. A compile that is refused, or killed before
it ends, keeps its staging so its sources and what rustc said can be read.
Each use of kompilator then removes every staging whose process no longer
runs, of every digest under ~/.stado/products/kompilator/ and not only the
one in use (a digest whose sources the toolchain refuses is never placed, and
one no installed Stado carries is never compiled again), and the older
staging-<uuid> ones an earlier Stado left, saying on stderr removed the kompilator staging <path> its ended compile left, or why one cannot be
removed; a staging whose process still runs is left to it. Each digest
directory is tagged CACHEDIR.TAG as well, so the janitor may reclaim a whole
digest under disk pressure, and the next use compiles it again.
No cargo check runs before a release build. kompilator tags its output and
unit store with CACHEDIR.TAG, so the janitor reclaims them under disk
pressure, and leaves one whose .lock a build holds or whose .in-use the run
that created it still holds; it also still reclaims a Kache store an older
Stado left.
A release manifest cannot ask for Cargo either. A quality gate, test step or
build of .wisent-release.json whose program is cargo (the bare name or any
path ending in it) is refused when the manifest is read — by stado quality check, stado release catalog sync and enroll,
stado build submit and stado release submit — as
stado.release.manifest.rule-broken, naming the step:
platforms.<platform>.quality.<name>.argv (or build.argv) runs "cargo", and Stado runs no Cargo: build a Rust crate with stado product kompilator stage --bin NAME and run a test with kompilator test --manifest-path Cargo.toml --test NAME; a cargo fmt or cargo clippy step has no replacement, since no Wisent gate formats or lints, so remove it. Replace or remove the step as the sentence says
and run the check again; it changes nothing.
What kompilator answers besides a build
Every Rust step of a product's own release, gates and scripts calls kompilator, never Cargo:
kompilator test --manifest-path <dir>/Cargo.toml [--lib] [--test NAME]…runs, ascargo testdoes, the unit tests inside the library (<out>/unittests/lib-<crate>) and each binary (<out>/unittests/bin-<name>) beside every integration test;--liband--test NAMEselect. A binary undersrc/bin/, andsrc/main.rsbeside a declared[[bin]], are built and tested as Cargo finds them.kompilator metadata --manifest-path <dir>/Cargo.tomlprints the workspace in the shape ofcargo metadata --no-deps --format-version 1: its root, its members and each target's kind and absolute source. Tama'stama hooks stage --kompilator <path>reads its binaries there.- A Git dependency is read from vendored sources when a build is handed them:
the directory
KOMPILATOR_GIT_SOURCESnames, else thesources/of theprivate-cargo-sourcesinput whose mountWISENT_INPUT_PRIVATE_CARGO_SOURCES_DIRnames; nothing is fetched while either is set, so a worker with no Git credential builds Spis, Ster, Skrzynka, Skarbiec or Jeden. A vendored directory that lacks a locked package is refused naming the package, the directory and the variable, and an entry vendored for another commit than the lock pins is refused naming both. kompilator vendor --manifest-path <dir>/Cargo.toml --out DIRwrites every Git package the lock names asDIR/<name>-<version>, the package's repository at its locked commit, files and directories only, so a package that inherits from its repository's workspace is read against it; its.kompilator-sourcenames the lock's source line it was vendored from.stado release catalog input pin --cargopublishes theprivate-cargo-sourcesinput with it (vendor-refusednames what kompilator said when a locked commit cannot be fetched).kompilator relock --manifest-path <dir>/Cargo.tomlwrites into the lock the version each workspace member now declares, changing only those entries and the dependency lines naming them, with nothing fetched;stado release loop's version step runs it after it bumps aCargo.tomlversion. A member the lock has no entry for, and a version the lock already holds from another source, are refused with the lock unchanged.kompilator lock --manifest-path <dir>/Cargo.tomlwrites into the lock every package a member newly asks for, with the packages those need, so a product that adopts a dependency is locked without Cargo: a crates.io one at the highest version the lock holds, else crates.io publishes, that meets its requirement (with the index's checksum); a Git one at the commit itsrev,branchortagnames now (git ls-remote). Optional dependencies are locked as the features asked of them turn them on, and a package the lock already holds keeps its entry. A workspace with no lock gets one. Arevthat is not a full commit, a path outside the workspace and a requirement nothing published meets are refused with the lock unchanged.kompilator run --manifest-path <dir>/Cargo.toml [--bin NAME | --example NAME] [-- ARGS]builds one binary or example asbuilddoes and runs it withARGSin the caller's directory, the program replacing kompilator, so its output, signals and exit status are its own: what a fleet job ran ascargo run --release -- …and a reader ascargo run --example NAME. Several binaries and no--bin, two--bin, and a--binwith an--example, are refused; a program its sources do not compile (exit 65) never runs.--result FILE(tobuild,testandrun) writes what the command came to as one JSON document:state, the command and theerrorthat ended it, themanifest_pathandsourcesbuilt (pinned to the commit--revisionnamed) and thefindings, each compiler errorrustcpointed into the sources with its header, code and<file>:<line>:<column>. It holds the fields Stado's retained Cargo results held, so Oko charges its findings to the commits that wrote those lines (oko sessions scorecard charges observe FILE). A document that cannot be written fails the command, naming the file.--example NAME(tobuild,runandwhere) links an example: a[[example]]table, orexamples/NAME.rsandexamples/NAME/main.rsunlessautoexamples = false, as a program against the package's library and its dev-dependencies, written as<out>/examples/NAME. A build of examples alone links no binary of the package. An example the package does not declare is refused naming those it does; one declared with acrate-typeother thanbinrefuses only a build that asks for it;testdoes not take--example.kompilator update --manifest-path <dir>/Cargo.toml --package NAME@FROM --precise TOmoves one crates.io package of the lock toTO, read from the crates.io index (checksum, yanked, dependencies), moving a locked dependency the new version needs higher to the highest published version every requirement on it admits, and adding nothing the lock lacks;stado product advisories applyruns it. A dependency it cannot place, a dependent whose requirement excludes the move and an unpublished or yanked version are refused with the lock unchanged.kompilator buildof a package that is a library alone compiles it and answers no path, as a gate that compiles every member of a workspace needs.- Cargo's profile overrides in the environment (
CARGO_PROFILE_DEV_DEBUG=line-tables-only,CARGO_PROFILE_<NAME>_<KEY>,CARGO_PROFILE_<NAME>_BUILD_OVERRIDE_<KEY>) apply over the manifest's[profile]; a value its setting does not take is refused naming the variable.--outand the unit store are made absolute before a build, so a--revisionbuild's scripts read an absoluteCARGO_MANIFEST_DIR. - CI takes kompilator from quality-control's action
(
wisent-ai/quality-control/.github/actions/kompilator): the runner's own, else compiled from Stado'smainwithrustcthrough a token that reads it; the sharedrust-gatesworkflow builds every package with it. - Every
gitkompilator starts leaves out the repository variables of its caller (git rev-parse --local-env-vars:GIT_DIR,GIT_INDEX_FILE, …), so a--revisionbuild started from a Git hook reads the manifest's own repository.
stado product kompilator has one operation, stage, above; any other
word is refused by the command line (exit 2), naming stage. A product's build
or test is kompilator build or kompilator test itself, and its workspace's
packages and targets are kompilator metadata. It was named stado product cargo while it ran no Cargo; that name is gone, and so is its results, which
read only the receipts an earlier Stado's Cargo runs left.
Before the build admission, a stage is refused as usage (exit 2) when
--manifest-path names no file (stado.product.kompilator.options.manifest-absent),
when a forwarded argument is neither --bin nor --features
(stage-argument), and when no --bin names a binary
(stage-binary-missing). Once admitted it is refused when WISENT_OUTPUT_DIR
is unset (output-unset) or relative (output-relative), and when a built
binary cannot be copied there (stado.product.kompilator.stage.staged-unplaced,
naming the binary, the destination and the system's answer). kompilator's own
refusals are stado.product.kompilator's.
Building on another host
stado host kompilator TARGET build --manifest-path PATH --revision REV --bin NAME… [--deadline SECONDS] [--json]
builds a committed revision on a fleet host with kompilator. Past --deadline
the processes the run started on the host are sent SIGTERM and the build fails
(ran past the declared --deadline of <N>s and was stopped), naming the
manifest, the binaries and what kompilator printed last; stado host upgrade builds through the same run with no deadline.
stado host kompilator TARGET gate --manifest-path RELEASE_MANIFEST --revision REV --gate NAME --platform PLATFORM [--json] runs one quality gate the revision's
release manifest declares, exactly as the submit queue runs it. PATH is a
crate's Cargo.toml inside its canonical checkout on this machine and REV a
commit that checkout holds; the manifest is read from the commit, never from
the working tree.
The commit is exported (no uncommitted edit is read) and delivered, with the
kompilator sources Stado carries, into a fresh run directory in TARGET's run
area: <work root>/runs when the registry declares a work root, else
$HOME/.stado/work/runs. TARGET compiles kompilator there once per source
digest with its own rustc — rustc could not compile kompilator from the sources Stado delivered, so nothing was built; … Select a Rust toolchain that compiles it (rust-toolchain.toml, or rustup default) when it cannot — and puts
it first on PATH. build runs kompilator build --release of each --bin
into the run's out; kompilator keeps its units in host-build/kompilator-units
of the host's build cache, shared by every run there. Each binary kompilator
answered is pulled back to <manifest directory>/target/host-kompilator/<commit>/<NAME>,
and the run directory is removed whatever the build answered; the exit status
is kompilator's. gate runs the declared argv in the delivered tree's root with
the release worker's contract (WISENT_SOURCE_DIR, WISENT_OUTPUT_DIR, an empty
WISENT_INPUTS_DIR, WISENT_VERSION, WISENT_PLATFORM) and the host's
installed Stado as STADO_BIN, first on PATH; the
submit queue runs every declared gate this way.
Refused before anything is exported, each naming its fix:
buildwithout--bin:a host build names the binaries it brings back; add --bin NAME for each;- any argument after
--:a host build runs kompilator, which takes no forwarded arguments; remove …(stado.host.runs.kompilator-request); - a path that is not a
Cargo.toml, or one outside any checkout on this machine (exit 2); - a commit the checkout does not hold (
fetch or commit it first), and a commit that holds no such manifest; - a host whose build-cache volume cannot hold a compile: the volume measured is
the one holding the build cache (below the declared work root when there is
one), and its free bytes must cover the janitor's margin — the largest build
measured there — plus what the running jobs hold; where that need is not
known, the janitor's disk-full threshold decides. The refusal names the free
bytes, the mount and the work root, with
stado host gates TARGETorstado space report TARGETto read what holds the room (exit 69).
A binary kompilator printed no path for is refused as kompilator answered no path for <binary> in <out>, so nothing of it was brought back. Every cause is
listed by stado errors show stado.host.run.build.
The build receipt (--json, schema stado.host-kompilator-receipt.v1) carries the
target, checkout, commit and archive_sha256 (the WISENT_SOURCE_SHA256 the
build was given), the manifest, the binaries asked for, kompilator's stdout,
stderr and exit_code, each brought-back binary with its path, bytes and
sha256, free_bytes_before and free_bytes_after (or free_bytes_after_error)
of the build-cache volume, and the removed run_directory. A gate's receipt
carries the commit, archive_sha256, the argv that ran, its streams and
exit_code, the run_directory, and stado_revision, the Stado that exported,
delivered and compiled the run.
Source: this website