Compiling Programs
Once you have written an SP1 program, you must compile it to an ELF file that can be executed in the zkVM. The cargo prove
CLI tool (downloaded during installation) provides convenient commands for compiling SP1 programs.
Development Builds
WARNING: Running
cargo prove build
may not generate a reproducible ELF which is necessary for verifying that your binary corresponds to given source code.Use SP1's reproducible build system for production builds.
To build a program while developing, simply run the following command in the crate that contains your SP1 program:
# Enter the directory containing your SP1 program.
cd path/to/your/program
# Build the program.
cargo prove build
This will compile the ELF that can be executed in the zkVM. The output from the command will look similar to this:
[sp1] Compiling version_check v0.9.4
[sp1] Compiling proc-macro2 v1.0.86
[sp1] Compiling unicode-ident v1.0.12
[sp1] Compiling cfg-if v1.0.0
...
[sp1] Compiling sp1-lib v1.0.1
[sp1] Compiling sp1-zkvm v1.0.1
[sp1] Compiling fibonacci-program v0.1.0 (/Users/username/Documents/fibonacci/program)
[sp1] Finished `release` profile [optimized] target(s) in 8.33s
Under the hood, this CLI command calls cargo build
with the riscv32im-succinct-zkvm-elf
target and other required environment variables and flags. The logic for this command is defined in the sp1-build crate.
Advanced Build Options
The cargo prove build
command supports several configuration options to customize the build process for your program:
--features
: Enable specific features--output-directory
: Specify a custom output location for the ELF--elf-name
: Set a custom name for the output ELF file--no-default-features
: Disable default features--locked
: Ensure Cargo.lock remains unchanged--packages
: Build only specified packages--binaries
: Build only specified binaries
Run cargo prove build --help
to see the complete list of options. Some options mirror those available in the standard cargo build
command.
Production Builds
For production builds, use Docker to generate a reproducible ELF that will be identical across all platforms. Simply add the --docker
flag to your build command. You can also specify a release version using --tag
, otherwise the tag defaults to the latest release. For example:
cargo prove build --docker --tag v4.0.0
To verify that your build is truly reproducible across different platforms and systems, compute the SHA-512 hash of the generated ELF file. The hash should be identical regardless of where you build it:
$ shasum -a 512 elf/riscv32im-succinct-zkvm-elf
f9afb8caaef10de9a8aad484c4dd3bfa54ba7218f3fc245a20e8a03ed40b38c617e175328515968aecbd3c38c47b2ca034a99e6dbc928512894f20105b03a203
Build Script
If you want your program crate to be built automatically whenever you build/run your script crate, you can add a build.rs
file inside of script/
(at the same level as Cargo.toml
of your script crate) that utilizes the sp1-build
crate:
fn main() {
sp1_build::build_program("../program");
}
The path passed in to build_program
should point to the directory containing the Cargo.toml
file for your program. Make sure to also add sp1-build
as a build dependency in script/Cargo.toml
:
[build-dependencies]
sp1-build = "4.0.0"
You will see output like the following from the build script if the program has changed, indicating that the program was rebuilt:
[fibonacci-script 0.1.0] cargo:rerun-if-changed=../program/src
[fibonacci-script 0.1.0] cargo:rerun-if-changed=../program/Cargo.toml
[fibonacci-script 0.1.0] cargo:rerun-if-changed=../program/Cargo.lock
[fibonacci-script 0.1.0] cargo:warning=fibonacci-program built at 2024-03-02 22:01:26
[fibonacci-script 0.1.0] [sp1] Compiling fibonacci-program v0.1.0 (/Users/umaroy/Documents/fibonacci/program)
[fibonacci-script 0.1.0] [sp1] Finished release [optimized] target(s) in 0.15s
warning: fibonacci-script@0.1.0: fibonacci-program built at 2024-03-02 22:01:26
The above output was generated by running RUST_LOG=info cargo run --release -vv
for the script
folder of the Fibonacci example.
Advanced Build Options
To configure the build process when using the sp1-build
crate, you can pass a BuildArgs
struct to to the build_program_with_args
function. The build arguments are the same as the ones available from the cargo prove build
command.
As an example, you could use the following code to build the Fibonacci example with the docker
flag set to true
and a custom name for the generated ELF. This will generate a reproducible ELF file (with Docker) with the name fibonacci-elf
:
use sp1_build::{build_program_with_args, BuildArgs};
fn main() {
let args = BuildArgs {
docker: true,
elf_name: "fibonacci-elf".to_string(),
..Default::default()
};
build_program_with_args("../program", &args);
}