Nix flake build for Lean 4.
Features:
- Build Lean with Nix
- Lean overlay from versions or toolchain files
- Build Lake projects (with executables, libraries, and facets) incrementally with Nix
- Convert
lake-manifest.jsoninto Nix dependencies
The default minimal template is for projects requiring manual dependency management:
nix flake new --template github:lenianiva/lean4-nix ./minimalThe .#dependency template shows an example of using lake-manifest.json to
fetch dependencies automatically.
nix flake new --template github:lenianiva/lean4-nix#dependency ./dependencyThe .#incremental template shows an example of incremental builds.
This project has CI by Garnix and uses
cache.garnix.io for binary caching. To use
the cache, there must be a match between the nixpkgs version listed in
flake.lock and the downstream project. Only the newest version will be cached.
The flake's packages.${system}.lean output contains the Lean and lake
executables. The version corresponds to the latest version in the manifests/
directory.
lean-all:leanandlakelean/leanc/lake: Executablesleanshared: Shared library of LeancacheRoots: Cached derivations to enable binary caching.buildLeanPackage: See below
The user must decide on a Lean version to use as overlay. The Lean version from
nixpkgs will likely not work of the box. The minimal supported version is
v4.11.0, since it is the version when Lean's official Nix flake was
deprecated. From version v4.22.0 onwards, each Lean build must have both
bootstrap and buildLeanPackage functions. There are a couple of ways to get
an overlay. Each corresponds to a flake output. Below is a list ranked from the
easiest to the hardest to use:
readToolchainFile { toolchain; binary ? true; }: Reads the toolchain from a file. Due to Nix's pure evaluation principle, this only supportsleanprover/lean4:{tag}basedlean-toolchainfiles. For any other toolchains, usereadRevorreadFromGit.readToolchain { toolchain; binary ? true };:readToolchainFilebut with its contents provided directly.readBinaryToolchain manifest: Reads the binary toolchain from a manifest given in the same format asmanifests/*.nix.tags.{tag}: Lean4 tags. See the available tags inmanifests/readRev { rev; bootstrap; buildLeanPackage; }: Reads a revision from the official Lean 4 repositoryreadFromGit{ args; bootstrap; buildLeanPackage; }: Given parameters tobuiltins.fetchGit, download a git repositoryreadSrc { src; bootstrap; buildLeanPackage; }: Builds Lean from a source folder. A bootstrapping function must be provided.
Then apply the overlay on pkgs:
pkgs = import nixpkgs {
inherit system;
overlays = [ (lean4-nix.readToolchainFile ./lean-toolchain) ];
};and pkgs.lean will be replaced by the chosen overlay.
Some users may wish to build nightly or release candidate versions without a
corresponding manifest in manifests/. In this case, a common solution is to
import the bootstrap and buildLeanPackage functions from the nearest major
version and feed it to readRev. In cases where there is a major change to the
bootstrap/buildLeanPackage function, the user may need to create the
function on their own.
This attribute set has properties
lean: The Lean executablelean-all:lean,lake, and the Lean library.example: Usenix run .#exampleto see an example of building a Lean program.Init,Std,Lean: Lean built-in libraries provided in the same format asbuildLeanPackage
and the function buildLeanPackage, which accepts a parameter set
{ name; roots; deps; src; }. The complete parameter set can be found in the
v4.22.0 manifest. In general:
src: The source directoryroots: Lean modules at the root of the import tree.deps: A list of outputs of otherbuildLeanPackagecalls.
This is a form of manual dependency management.
Use lake2nix = pkgs.callPackage lean4-nix.lake {} to generate the lake utilities.
lake2nix.buildDeps { ... } automatically reads the lake-manifest.json file
and builds its dependencies using lake build. The output is an attr set of
derivations for each dependency. It takes the following arguments:
src: The source directorymanifestFile ? ${src}/lake-manifest.json: Path to the manifest filedepOverride ? {}: Attr set of any custom arguments to use when building a given dependency, such asbuildPhaseorpreConfigure.depOverrideDeriv ? {}: Attr set of derivations to use instead of building dependencies
lake2nix.mkPackage { ... } builds the given build target of the Lake project
using lake build, optionally with the dependencies built by buildDeps. The
output is a derivation. It takes the following arguments:
name: The name of the desired target to buildsrc: The source directory name frommanifestFilestaticLibDeps ? []: List of static libraries to link with.lakeDeps: If provided, use these dependencies instead of callingbuildDepsinternallylakeArtifacts: If provided, copy the.lakeartifacts from another derivation for incremental buildsbuildLibrary ? false: Whether to build library facets for thenamebuild targetinstallArtifacts ? true: Whether to export.lakeartifacts and source in the derivationoutPathfor incremental buildsconfigurePhase: If provided, override the configure phasebuildPhase: If provided, override the build phaseinstallPhase: If provided, override the install phase
The buildLeanPackage function output the built Lean package
in a non-derivation format. Generally, the attributes available are:
executable: ExecutablesharedLib: Shared librarymodRoot: Module root. SetLEAN_PATHto this to provide context for LSP.cTree,oTree,iTree: Trees of C files/.ofiles/.ileanfiles
The Lean version is not listed in the manifests/ directory. Use readRev or
readFromGit instead.
Use the provided pre-commit config:
prek installUse nix flake check to check the template builds.
Update the template lean-toolchain files when new Lean versions come out. When
a new version is released, execute
nix run .#toolchain-fetch $VERSION [$VERSION_TAG]to generate new toolchain hashes. Supply $VERSION_TAG to address any version
tag mismatches (e.g. 4.20.1 incorrectly tagged as 4.20.0).
All code must be formatted with alejandra before merging into main. To use
it, execute
nix fmt .