Lake Build System
Lake is Lean's build system and package manager. It handles dependencies, compilation, and project configuration.
Creating a New Project
The lake new command scaffolds a complete project. Which files you get depends on the template:
1# std (default) - a library AND an executable2lake new myproject34# exe - executable only5lake new myapp exe67# lib - library only8lake new mylib lib910# math - library preconfigured with Mathlib, linting, and CI11lake new myproofs math1213# Same thing, but in the CURRENT directory instead of a new one14lake init myproject1516# Pin the Lean version at creation time (via elan)17lake +leanprover/lean4:v4.32.1 new myproject.lean or .tomlto a template name to choose the configuration file format โ lake new myproject std.lean gives you a lakefile.lean. TOML is the default in current Lake, and is what you should prefer unless you need to compute something in the config.This creates a project structure:
1myproject/2โโโ lakefile.toml # Build configuration3โโโ lean-toolchain # Pinned version, e.g. leanprover/lean4:v4.32.14โโโ Main.lean # Entry point for the executable5โโโ Myproject.lean # Library root: usually just imports the modules below6โโโ Myproject/7โ โโโ Basic.lean # Library code8โโโ .github/workflows/ # CI that runs lake build9โโโ .gitignore # Ignores .lake/Myproject.lean and Myproject/. That is Lean's module convention: the file is the module Myproject, and everything in the directory is Myproject.Something. The root file typically contains nothing but import lines, so a user can write import Myproject and get everything.The lakefile
This is what lake new myproject actually generates:
1name = "myproject"2version = "0.1.0"3defaultTargets = ["myproject"]45[[lean_lib]]6name = "Myproject"78[[lean_exe]]9name = "myproject"10root = "Main"The same configuration in the Lean DSL, which you get with the .lean template suffix:
1import Lake2open Lake DSL34package myproject where5 leanOptions := #[โจ`autoImplicit, falseโฉ]67@[default_target]8lean_lib Myproject910lean_exe myproject where11 root := `Mainmain). Use the TOML form for ordinary projects; reach for the Lean DSL only when you need custom targets, scripts, or computed options.Basic Lake Commands
These commands handle everyday development tasks. Run them from the project root directory.
1# Build the project2lake build34# Build and run an executable5lake exe myapp67# Clean build artifacts8lake clean910# Update dependencies11lake update1213# Get help14lake helpAdding Dependencies
Add external packages to your lakefile:
1import Lake2open Lake DSL34package myproject where5 -- Dependencies go here67-- From the Reservoir registry, pinned to a tag or revision8require "leanprover-community" / "mathlib" @ git "v4.32.0"910-- Batteries (formerly std4 - the old name no longer resolves)11require "leanprover-community" / "batteries" @ git "main"1213-- Local dependency14require localLib from ".." / "local-lib"1516@[default_target]17lean_lib MyprojectOr, equivalently, in lakefile.toml:
1[[require]]2name = "mathlib"3scope = "leanprover-community"4rev = "v4.32.0"main. Mathlib and Lean move in lockstep: a Mathlib revision only builds against the Lean version it was written for. If you see hundreds of errors in library code after a lake update, your lean-toolchainand your Mathlib revision have drifted apart.After adding dependencies:
1# Fetch and build dependencies2lake update3lake build.lake directory. This folder is typically gitignored.Understanding .lake
The .lake directory stores build artifacts, downloaded dependencies, and generated files. You can safely delete it to force a clean rebuild.
Project Targets
Libraries
A library target makes modules available for import by other code. Specify which modules belong to this library using the roots field.
1-- A library with specific root modules2lean_lib MyLib where3 roots := #[`MyLib]4 5-- Multiple root modules6lean_lib Utilities where7 roots := #[`Utils.String, `Utils.Math, `Utils.IO]89-- Exclude certain modules from build10lean_lib Core where11 roots := #[`Core]12 globs := #[.submodules `Core]Executables
An executable target produces a runnable program. The root field points to the module containing the main function.
1-- Basic executable2lean_exe myapp where3 root := `Main45-- Executable with dependencies6lean_exe cli where7 root := `CLI.Main8 -- This exe depends on the MyLib library9 -- (usually automatic)The lean-toolchain File
This file specifies the Lean version:
1leanprover/lean4:v4.32.1When you run lake, it ensures the correct Lean version is used. This guarantees reproducible builds.
Deep Dive: Lean Toolchain Management
The toolchain file works with elan, Lean's version manager:
1# Install elan (if not already)2curl https://raw.githubusercontent.com/leanprover/elan/master/elan-init.sh -sSf | sh34# List installed toolchains5elan show67# Install a specific version8elan install leanprover/lean4:v4.32.1910# Set default toolchain11elan default leanprover/lean4:stableConfiguration Options
1package myproject where2 -- Lean compiler options3 leanOptions := #[4 โจ`pp.unicode.fun, trueโฉ, -- Use ฮป instead of fun5 โจ`autoImplicit, falseโฉ -- Disable auto-implicit6 ]7 8 -- Stricter warnings9 moreServerOptions := #[10 โจ`warningAsError, trueโฉ11 ]1213lean_lib MyLib where14 -- Library-specific options15 defaultFacets := #[LeanLib.sharedLib] -- Build shared libraryScripts and Custom Commands
1-- Scripts live in lakefile.lean (the TOML format has no equivalent).2-- A script returns a UInt32 exit code.3script test do4 IO.println "Running tests..."5 -- Your test logic here6 return 078script format do9 IO.println "Formatting code..."10 return 01# List the scripts a project defines2lake script list34# Run one. "lake run" is an alias for "lake script run".5lake run test6lake script run formatCreate a script that prints the Lean version used by your project.
1script showVersion do2 IO.println s!"Lean toolchain: {(โ IO.FS.readFile "lean-toolchain").trimAscii}"3 return 0Common Workflows
Starting a New Project
1lake new myproject2cd myproject3lake build4lake exe myproject # If it's an executableAdding Mathlib
By far the easiest route is to let the template do it:
1lake new myproofs math2cd myproofs3lake exe cache get # Download prebuilt .olean files - do this FIRST4lake buildTo add Mathlib to an existing project, put the dependency in your lakefile and then:
1# 1. Match lean-toolchain to the Mathlib revision you are requiring2# 2. Fetch the dependency3lake update mathlib4# 3. Download prebuilt artifacts instead of compiling Mathlib yourself5lake exe cache get6# 4. Build7lake buildlake exe cache get when using Mathlib to download pre-compiled files instead of building from sourceโsaves hours of compile time.