Skip to main content
Version: 4.0.0

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);
}