Buck2 Integration
Turnkey provides first-class Buck2 integration with automatic toolchain and dependency cell generation.
Enabling Buck2
In your flake.nix:
turnkey.toolchains = {
enable = true;
declarationFiles.default = ./toolchain.toml;
buck2.enable = true;
};
By default only the default shell gets the Buck2 integration: the pinned
buck2 on its PATH, the prelude, and the generated cells. List other shells
in buck2.shells to give them the integration too:
turnkey.toolchains = {
declarationFiles = {
default = ./toolchain.toml;
ci = ./toolchain.ci.toml;
docs = ./docs/toolchain.toml; # no Buck2 here
};
buck2 = {
enable = true;
shells = [ "default" "ci" ];
};
};
Naming a shell that declarationFiles doesn't define is an error.
The buck2 version
Each turnkey revision ships exactly one buck2 release, together with the
prelude built with it. You don't choose buck2 in toolchain.toml: you get
a newer buck2 by updating your turnkey input (nix flake update turnkey).
Turnkey's test runner speaks buck2's internal test protocol and its prelude
is patched for one prelude revision, so each only works against the release
it was built for
(ADR 0002).
To see which release you have, read turnkey.toolchains.buck2.version, or
look at the shell's welcome message, which ends with (buck2 <version>)
when a welcomeMessage is set.
Migrating from a declared buck2
Earlier turnkey revisions took buck2 from toolchain.toml. Declaring it now
fails evaluation:
error: turnkey: /nix/store/…-source/toolchain.toml declares buck2-toolchain, but turnkey now ships buck2 itself.
To migrate:
- Remove the
buck2orbuck2-toolchainentry from everytoolchain.toml. - Keep
buck2.enable = true;inflake.nix. If a shell other thandefaultused to declare buck2, add its name tobuck2.shells. Before, declaring buck2 is what gave a shell the Buck2 integration. buck2-toolchainalso carriedreindeer. If you use it, declarereindeer = {}intoolchain.toml.
To run a different buck2 anyway, override turnkey's toolbox input with
follows. This is unsupported: test result caching or the prelude may break
against another release.
Generated Cells
When Buck2 integration is enabled, Turnkey generates:
Toolchains Cell
Located at .turnkey/toolchains/, contains toolchain rules for each declared language:
toolchains//:go- Go toolchaintoolchains//:rust- Rust toolchaintoolchains//:python- Python toolchain- etc.
It also holds toolchains//conditions:<os>-<cpu>, one config_setting per
platform in buck2.platforms (the flake's systems by default), combining
its OS and CPU constraints. Rules sync keys a select() on one when deps
differ by CPU within one OS
(Platform-Conditional Deps).
With buck2.go.allowedBuildTags, which also sets .buckconfig's
go.allowed_build_tags, it holds the settings combining the platform's OS
and CPU with each allowed tag, set (linux-x86_64-integration) or unset
(linux-no_integration), for a Go library whose imports depend on a tag.
Prelude Cell
The Buck2 prelude is provided via Nix at .turnkey/prelude/: the prelude built with turnkey's pinned buck2 release, with turnkey's patches and extensions applied.
The prelude and toolchains cells are symlinks into the Nix store. After
either changes, a plain buck2 call needs a tk call or a buck2 kill
first: see Symlinked Cells and Plain buck2.
A Prelude of Your Own
prelude.path replaces turnkey's prelude with a derivation or a path. It is
off the supported path, and it turns test result caching off:
turnkey.toolchains.buck2.prelude.path = ./my-prelude;
Directories Buck2 Doesn't See
The generated .buckconfig's project.ignore lists directories, relative to
the project root, that buck2 skips: //... doesn't load their rules.star
files, and buck2's file watcher drops their events, so they never show up as
File changed: lines. turnkey always ignores two kinds of directory that no
build reads but something writes to all the time:
- the VCS's metadata:
.git,.jj,.hg,.sl; - the devenv and direnv state:
.devenv,.direnv.
ignore adds to them. Use it for trees that are projects of their own, such
as test fixtures whose targets only build in their own checkout:
turnkey.toolchains.buck2.ignore = [ "e2e/fixtures" ];
Buck2 reads project.ignore when its daemon starts, so a change takes effect
once the daemon restarts. .buckconfig is a store symlink, so tk restarts
it on its next command; plain buck2 needs a buck2 kill first
(Symlinked Cells and Plain buck2).
Dependency Cells
Language-specific dependency cells are generated when configured:
godeps//- Go dependencies from go-deps.tomlrustdeps//- Rust dependencies from rust-deps.tomlpydeps//- Python dependencies from python-deps.tomljsdeps//- JavaScript dependencies from js-deps.tomlsoldeps//- Solidity dependencies from solidity-deps.toml
They are write-once directories, which plain buck2 reads without a daemon
restart.
See Managing Dependencies for configuration details.