Skip to content

Build Guide

ESBMC builds on Linux, macOS, FreeBSD and Windows. Pick your platform below and follow the steps. Each tab produces a working esbmc with the Z3 solver; the heavier dependencies (LLVM/Clang, fmt, nlohmann-json, yaml-cpp and immer) are downloaded and built automatically with -DDOWNLOAD_DEPENDENCIES=1 where the platform supports it.

Note

At least 6 GB of RAM is recommended. ESBMC is distributed mainly under the Apache License 2.0.

For a build with several solvers, or CHERI/fuzzing support, see Building with all solvers and Advanced.

Build ESBMC

Install prerequisites

sudo apt-get update
sudo apt-get install -y build-essential cmake ninja-build git bison flex \
  python3 libboost-all-dev g++-multilib

LLVM/Clang, Z3 and the libraries fmt, nlohmann-json, yaml-cpp and immer are fetched by -DDOWNLOAD_DEPENDENCIES=1, so they are not installed here.

Get the source

git clone https://github.com/esbmc/esbmc.git
cd esbmc

Configure and build

cmake -GNinja -Bbuild -DDOWNLOAD_DEPENDENCIES=1 -DENABLE_Z3=1
ninja -C build

The binary is written to build/src/esbmc/esbmc.

Optional: run the regression tests

Add the testing flags when configuring, then run ctest:

cmake -GNinja -Bbuild -DDOWNLOAD_DEPENDENCIES=1 -DENABLE_Z3=1 \
  -DBUILD_TESTING=On -DENABLE_REGRESSION=On
ninja -C build
ctest --test-dir build -j"$(nproc)" -L esbmc --timeout 120
Optional: enable a frontend or extra solvers

For Python, Solidity or IBEX support see Optional frontends. For a multi-solver build see Building with all solvers.

Dependency reference

packagerequiredminimum version
clangyes11.0.0
boostyes1.77
CMakeyes3.18.0
Boolectorno3.2.2
CVC4no1.8
CVC5no1.1.2
MathSATno5.5.4
Yicesno2.6.4
Z3no4.13.3
Bitwuzlano0.9.0

The version requirements are stable but can change between releases. For all available CMake options, see Options.cmake.

Optional frontends

These are extra CMake flags added to the configure step in any platform tab above.

Python

Add -DENABLE_PYTHON_FRONTEND=On to the configure step:

cmake -GNinja -Bbuild -DDOWNLOAD_DEPENDENCIES=1 -DENABLE_Z3=1 -DENABLE_PYTHON_FRONTEND=On

ast2json is vendored in the source tree, so no pip install is needed. Optionally install mypy (e.g. pipx install mypy) for Python type checks.

Solidity

Add -DENABLE_SOLIDITY_FRONTEND=On to the configure step. The Solidity frontend verifies smart contracts against predefined safety properties (bounds, overflow, underflow) and user-defined assertions.

IBEX (interval constraint solving)

Enables --goto-contractor. Install IBEX following its instructions, then:

cmake -GNinja -Bbuild -DENABLE_GOTO_CONTRACTOR=ON -DIBEX_DIR=path-to-ibex

API documentation

Add -DBUILD_DOC=On to the configure step to build the Doxygen API reference alongside ESBMC (requires doxygen and graphviz). See the API Reference guide for details.

Building with all solvers

ESBMC supports Bitwuzla, Boolector, CVC4, CVC5, MathSAT, Yices 2 and Z3. All are optional, but without at least one solver ESBMC cannot verify most programs. For a single-solver build, the platform tabs above are enough.

The recipe below mirrors the multi-solver build used in ESBMC’s CI: build each solver into the project directory, then point the configure step at them. Build only the solvers you need.

Prepare a Clang/LLVM toolchain

For a static build, let ESBMC download Clang/LLVM:

ESBMC_CLANG=-DDOWNLOAD_DEPENDENCIES=On
ESBMC_STATIC=ON

For a shared build, use the system LLVM/Clang instead (Ubuntu example):

sudo apt-get install libclang-cpp16-dev
ESBMC_CLANG="-DLLVM_DIR=/usr/lib/llvm-16/lib/cmake/llvm -DClang_DIR=/usr/lib/cmake/clang-16"
ESBMC_STATIC=OFF

Build the solvers

Boolector
git clone --depth=1 --branch=3.2.3 https://github.com/boolector/boolector && cd boolector && ./contrib/setup-lingeling.sh && ./contrib/setup-btor2tools.sh && ./configure.sh --prefix $PWD/../boolector-release && cd build && make -j9 && make install && cd ../..
Z3
# Linux
wget https://github.com/Z3Prover/z3/releases/download/z3-4.13.3/z3-4.13.3-x64-glibc-2.35.zip && unzip z3-4.13.3-x64-glibc-2.35.zip && mv z3-4.13.3-x64-glibc-2.35 z3
# macOS
brew install z3 && cp -rp $(brew info z3 | egrep "/usr[/a-zA-Z\.0-9]+ " -o) z3
Bitwuzla

Requires MPFR >= 4.2.1 (apt-get install libmpfr-dev / brew install mpfr).

git clone --depth=1 --branch=0.9.0 https://github.com/bitwuzla/bitwuzla.git && cd bitwuzla && ./configure.py --prefix $PWD/../bitwuzla-release && cd build && meson install && cd ../..
CVC4 (Linux only)
pip3 install toml && git clone https://github.com/CVC4/CVC4.git && cd CVC4 && git reset --hard b826fc8ae95fc && ./contrib/get-antlr-3.4 && ./configure.sh --optimized --prefix=../cvc4 --static --no-static-binary && cd build && make -j4 && make install && cd ../..
CVC5
pip3 install toml && git clone https://github.com/CVC5/CVC5.git && cd CVC5 && git switch --detach cvc5-1.1.2 && ./configure.sh --prefix=../cvc5 --auto-download --static --no-static-binary && cd build && make -j4 && make install && cd ../..
MathSAT
# Linux
wget http://mathsat.fbk.eu/release/mathsat-5.5.4-linux-x86_64.tar.gz -O mathsat.tar.gz && tar xf mathsat.tar.gz && mv mathsat-5.5.4-linux-x86_64 mathsat
# macOS
wget http://mathsat.fbk.eu/release/mathsat-5.5.4-darwin-libcxx-x86_64.tar.gz -O mathsat.tar.gz && tar xf mathsat.tar.gz && mv mathsat-5.5.4-darwin-libcxx-x86_64 mathsat && ln -s /usr/local/include/gmp.h mathsat/include/gmp.h
Yices (Linux)

Yices needs a static GMP first:

wget https://gmplib.org/download/gmp/gmp-6.1.2.tar.xz && tar xf gmp-6.1.2.tar.xz && cd gmp-6.1.2 && ./configure --prefix $PWD/../gmp --disable-shared ABI=64 CFLAGS=-fPIC CPPFLAGS=-DPIC && make -j4 && make install && cd ..
git clone https://github.com/SRI-CSL/yices2.git && cd yices2 && git checkout Yices-2.6.4 && autoreconf -fi && ./configure --prefix $PWD/../yices --with-static-gmp=$PWD/../gmp/lib/libgmp.a && make -j9 && make static-lib && make install && cp ./build/x86_64-pc-linux-gnu-release/static_lib/libyices.a ../yices/lib && cd ..

Configure and build ESBMC

Pass the directories of the solvers you built. Drop the flags for any solver you skipped.

cd esbmc && cmake -GNinja -Bbuild -DBUILD_TESTING=On -DENABLE_REGRESSION=On \
  $ESBMC_CLANG -DBUILD_STATIC=${ESBMC_STATIC:-ON} \
  -DBoolector_DIR=$PWD/../boolector-release -DZ3_DIR=$PWD/../z3 \
  -DENABLE_MATHSAT=ON -DMathsat_DIR=$PWD/../mathsat \
  -DENABLE_YICES=On -DYices_DIR=$PWD/../yices -DCVC4_DIR=$PWD/../cvc4 \
  -DGMP_DIR=$PWD/../gmp -DBitwuzla_DIR=$PWD/../bitwuzla-release \
  -DCMAKE_INSTALL_PREFIX:PATH=$PWD/../release
ninja -C build && ninja -C build install

ESBMC is installed into the release folder. Add -DCMAKE_BUILD_TYPE=Debug to enable ESBMC’s internal assertions.

Advanced

Build in a Docker container

A minimal Debian-based image that builds ESBMC with Z3, letting -DDOWNLOAD_DEPENDENCIES=1 fetch LLVM/Clang and the libraries:

FROM ubuntu:24.04
RUN apt-get update && apt-get install -y --no-install-recommends \
      build-essential cmake ninja-build git bison flex \
      python3 libboost-all-dev g++-multilib \
    && rm -rf /var/lib/apt/lists/*
RUN git clone --depth=1 https://github.com/esbmc/esbmc.git /esbmc
WORKDIR /esbmc
RUN cmake -GNinja -Bbuild -DDOWNLOAD_DEPENDENCIES=1 -DENABLE_Z3=1 \
    && ninja -C build

Build the image with docker build -t esbmc .; the binary is at /esbmc/build/src/esbmc/esbmc.

Shared (dynamic) builds

A non-static ESBMC links against system libraries/solvers. Shared linking is the default when CMake is invoked with -DBUILD_STATIC=Off (or the variable unset).

When Clang is built with CLANG_LINK_CLANG_DYLIB=On, ESBMC links the dynamic libclang-cpp and does not bundle Clang’s headers. Header bundling is controlled by CLANG_HEADERS_BUNDLED (On/Off/detect); the default detect bundles headers only for static Clang links. Not bundling speeds up source translation by avoiding a temporary header-extraction directory, but ESBMC must be recompiled when the system Clang is updated.

CHERI-C support (experimental)

CHERI-enabled ESBMC uses CHERI Clang (release 20210817, clang 13). Build it, then configure ESBMC against it:

wget https://github.com/CTSRD-CHERI/llvm-project/archive/refs/tags/cheri-rel-20210817.tar.gz
sudo apt-get install lld
tar xf cheri-rel-20210817.tar.gz && mkdir clang13 && cd llvm-project-cheri-rel-20210817 && mkdir build && cd build
cmake -GNinja -S ../llvm -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_PROJECTS='llvm;clang' -DLLVM_INSTALL_BINUTILS_SYMLINKS=TRUE -DLLVM_ENABLE_LIBXML2=FALSE -DLLVM_ENABLE_ZLIB=FALSE '-DLLVM_TARGETS_TO_BUILD=AArch64;ARM;Mips;RISCV;X86;host' -DCMAKE_INSTALL_PREFIX=../../clang13
ninja && ninja install && cd ../..
ESBMC_CLANG=$(echo -D{LLVM,Clang}_DIR=$PWD/clang13)

A CHERI sysroot is needed for programs that use the C standard library. The cheribuild tool is the recommended way to obtain one:

git clone https://github.com/CTSRD-CHERI/cheribuild.git && cd cheribuild && python3 cheribuild.py cheribsd-sdk-riscv64-purecap -d

Then configure ESBMC with:

-DESBMC_CHERI=On -DESBMC_CHERI_HYBRID_SYSROOT=<path> -DESBMC_CHERI_PURECAP_SYSROOT=<path>

e.g. <path> pointing at $HOME/cheri/output/sdk/sysroot-riscv64-purecap.

Fuzzing targets

ESBMC ships libFuzzer targets. They must be built with Clang, so configure ESBMC to use it and enable fuzzing:

cmake -GNinja -Bbuild -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DENABLE_FUZZER=1

Passing the compiler options for the first time clears the CMake cache, so some variables may need to be re-set.