Prerequisites
Install cargo-dylint and dylint-link:
cargo install cargo-dylint dylint-link
The published whitaker-installer crate requires Rust 1.85 or newer. This is
the first stable compiler that supports the Rust 2024 edition used by the
installer.
Published x86_64 GNU/Linux installer, dependency, and lint artefacts target the
Ubuntu 22.04 GLIBC_2.35 baseline and do not require a newer glibc version. On
an incompatible system, build Whitaker and its dependencies from source instead
of using the published Linux artefacts.
Standalone installation (recommended)
The simplest way to use Whitaker is via the standalone installer, which handles setup automatically:
cargo install whitaker-installer
whitaker-installer
whitaker --all
This:
- Installs
cargo-dylintanddylint-linkif not present The installer first attempts to download pre-built dependency binaries from Whitaker's GitHub Releases page for the current platform. If the release asset is absent (HTTP 404 or 410), the installer skipscargo binstalland falls back directly to building from source withcargo install, pinned to the version recorded in the dependency manifest. If the release asset is present but the download fails for another reason, the installer falls back tocargo binstallwhen available and then tocargo install. When the source-build path is taken, the installer reports that it is falling back to Cargo, and on success it printsInstalled <tool> from source with cargo install.. After installation,cargo-dylintis verified by runningcargo dylint --version.dylint-linkis never executed: it is a linker wrapper that forwards its arguments to the underlying linker, so it has no reliable self-reporting subcommand. A release artefact is trusted once its checksum, extraction, and executable permissions have been established, and a Cargo-managed copy is checked by resolving it onPATHand comparing the version Cargo recorded. - Clones the Whitaker repository to a platform-specific data directory
- Builds the lint libraries
- Creates
whitakerandwhitaker-lswrapper scripts.whitakerinvokescargo dylintwith the correctDYLINT_LIBRARY_PATH, andwhitaker-lslists installed Whitaker suite libraries - Ensures the pinned Rust toolchain and components are installed via rustup
After installation, run whitaker --all in any Rust project to lint it. Use
whitaker-ls to list the installed Whitaker suite libraries.
On Windows, the installer's PATH check honours PATHEXT and falls back to
the usual executable suffixes when PATHEXT is unset, so a normal
Cargo-installed executable such as dylint-link.exe in
%USERPROFILE%\.cargo\bin is located correctly and then matched against the
version Cargo recorded for it, without needing a separate wrapper or manual
environment-variable workaround.
Options:
--cranelift— Tell the installer to add therustc-codegen-craneliftcomponent viarustup component add. Therustc-codegen-craneliftcomponent is not included in the standard nightly toolchain, so enable--craneliftwhen a project or CI pipeline requires the Cranelift back-end and would otherwise need an explicitrustc-codegen-craneliftcomponent-add step before running the installer.--skip-deps— Skipcargo-dylint/dylint-linkinstallation check--skip-wrapper— Skip wrapper script generation (printsDYLINT_LIBRARY_PATHinstructions instead)--no-update— Don't update existing repository clone--suite-version REF(alias--suite-ref) — Build the lint suite from a given tag, branch or commit rather than from the default branch tip. See Pinning the lint suite--no-source-fallback— Fail rather than build from source when a published artefact is absent. See Refusing a source build
Adding Whitaker to a project
Add the following to the workspace Cargo.toml:
[workspace.metadata.dylint]
libraries = [
{ git = "https://github.com/leynos/whitaker", pattern = "whitaker_suite" }
]
Then run the lints:
cargo dylint --all
Pinning the lint suite
The installer builds the suite from a Whitaker checkout. Without a pin it uses
whatever is at the default branch tip, so a change to that branch alters lint
results with no commit in the consuming repository: a gate can turn red on a
branch that has not been touched. --suite-version names the reference to
build from instead, so a suite change arrives as a reviewed bump.
whitaker-installer --suite-version v0.2.7
It accepts a tag, a branch or a commit, and the installer hands it to git to
resolve.
Two consequences are worth knowing before pinning.
A pinned suite is built from source. Prebuilt lint libraries are published
only for the branch tip, under the rolling tag, so a pin can never be served
from them; the installer does not attempt the download at all when a pin is
set, and compiles the suite locally instead. Pinning trades install time for
reproducibility, and that is the whole of the trade: a pinned lane is slower on
a cold cache and does not change what it produces.
The prebuilt path would not help a pin even if artefacts existed for every tag.
A lint library must be built with the exact toolchain that will load it, and
artefacts are named for the toolchain they were built with, so a pin held
against a newer rust-toolchain.toml misses and builds from source anyway. The
guarantee a pin buys is reproducibility, not speed.
With --no-update, an already-local --suite-version reference resolves
without network access. A later unpinned update reattaches a detached managed
clone to its default branch before pulling.
A pin cannot be applied from inside a Whitaker checkout. Checking out a reference there would move the working tree, so the installer refuses and says so. Run it from another directory, where it manages its own clone, or check out the reference directly.
Pinning the installer and pinning the suite are separate decisions. The
installer's version selects the tool; --suite-version selects the lints it
builds.
Version pinning through Cargo metadata
When Dylint is driven directly rather than through the installer, pin to a specific release tag or commit:
[workspace.metadata.dylint]
libraries = [
{ git = "https://github.com/leynos/whitaker", pattern = "whitaker_suite", tag = "v0.1.0" }
]
Or pin to a specific commit:
[workspace.metadata.dylint]
libraries = [
{ git = "https://github.com/leynos/whitaker", pattern = "whitaker_suite", rev = "abc123def456" }
]
Rolling release downloads
Whitaker publishes a rolling pre-release tag that is continuously updated and
overwritten on every push to main. It is intended for early adopters who want
the latest available build outputs before the next stable release is cut.
Rolling releases are best-effort builds. If some matrix legs fail, Whitaker
still publishes the artefacts that were built successfully. For example, a
target-specific cargo-dylint archive may be missing from one rolling release
even though other target archives were updated successfully. Do not assume that
every supported target is present in every rolling release.
This best-effort policy applies to ordinary pushes and unforced manual runs. A
forced manual dependency-binary rebuild is a recovery operation: it republishes
only after both five-target build matrices and all required lint, manifest,
dependency, and checksum assets pass validation. If that check fails, the
existing rolling release remains unchanged.
Stable releases differ from rolling: a stable tag is expected to contain the
complete artefact set for the release. For production installs, pin to a stable
release tag rather than consuming rolling.
Scripts or CI pipelines that consume rolling-release archives should verify that the required target archive exists before proceeding. Treat missing archives as an expected condition for rolling releases rather than assuming the artefact set is complete.
Refusing a source build
The installer prefers published binaries and falls back to building from source
when one is missing: a prebuilt lint library becomes a local compilation, and a
Dylint tool archive becomes cargo install. Both succeed, which is the
difficulty. A run that took either reports success while having built something
nobody pinned, and the only sign is a line in the log.
--no-source-fallback, or WHITAKER_NO_SOURCE_FALLBACK in the environment for
callers that cannot easily add a flag, turns each fallback into an error naming
the artefact and why it could not be fetched:
whitaker-installer --no-source-fallback
Any value other than an empty string, 0 or false enables the rule. The
comparison ignores case and surrounding whitespace, so FALSE and false
also turn it off. Exporting the variable at all expresses an intention, and
reading an unrecognized value as off would quietly remove a protection; a value
that is not valid text enables the rule for the same reason.
The flag is rejected alongside --build-only, --experimental and
--suite-version. Each of those requires a source build, so combining them is
a contradiction rather than a preference, and the installer says so instead of
silently preferring one.
Each installation that selects a suite source prints the path it took on standard output. A dry run selects none, so it prints nothing:
whitaker-installer: suite-source=prebuilt
The value is prebuilt or source. It reports where the suite came from and
adds to the existing checks rather than replacing them: install-whitaker
still scans the installer's standard error for the fallback notice and fails an
unapproved source build on what it finds there. Reading only the marker would
let a source build the marker missed pass as prebuilt.
The streams are separate on purpose. The marker is the only thing on standard output, so it can be parsed; the fallback notice and every other diagnostic go to standard error.
The rolling release is the reason this exists. It is republished on every push
to main, and a consumer whose install starts during a republish can miss an
archive that is present moments later. In CI a source build is a defect rather
than a degraded mode, so fail and retry rather than proceeding.
Selecting individual lints
To load specific lints instead of the full suite, specify each lint explicitly:
[workspace.metadata.dylint]
libraries = [
{ git = "https://github.com/leynos/whitaker", pattern = "crates/module_max_lines" },
{ git = "https://github.com/leynos/whitaker", pattern = "crates/no_expect_outside_tests" }
]
Standard vs Experimental Lints
Whitaker lints are divided into two categories:
- Standard lints are stable, well-tested, and included in the default suite. They are recommended for general use and have predictable behaviour.
- Experimental lints are newer or more aggressive checks that may produce false positives or undergo breaking changes between releases. They must be explicitly enabled.
The default whitaker_suite pattern includes only standard lints. Whitaker
currently ships one experimental lint, rstest_helper_should_be_fixture, which
is available only when experimental lints are enabled.
Enabling experimental lints
Via standalone installer
whitaker-installer --experimental
This enables experimental suite features when building whitaker_suite. To
build experimental lints as individual libraries, combine it with
--individual-lints. Explicit --lint requests for experimental lints also
require --experimental; without that opt-in the installer rejects the request
before building anything.