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.
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++-multilibLLVM/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 esbmcConfigure and build
cmake -GNinja -Bbuild -DDOWNLOAD_DEPENDENCIES=1 -DENABLE_Z3=1
ninja -C buildThe binary is written to build/src/esbmc/esbmc.
Optional: run the regression tests
Add the testing flags when configuring, then run ctest:
CXX=g++ CC=gcc 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 120Optional: 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
| package | required | minimum version |
|---|---|---|
| clang | yes | 11.0.0 |
| boost | yes | 1.77 |
| CMake | yes | 3.18.0 |
| Boolector | no | 3.2.2 |
| CVC4 | no | 1.8 |
| CVC5 | no | 1.1.2 |
| MathSAT | no | 5.5.4 |
| Yices | no | 2.6.4 |
| Z3 | no | 4.13.3 |
| Bitwuzla | no | 0.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=Onast2json 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-ibexAPI 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.
ESBMC can additionally drive Bitwuzllob — Bitwuzla running on the massively
parallel Mallob platform — as an external
process; see Using Bitwuzllob below. It needs no build-time
setup (the backend is enabled by default, -DENABLE_BITWUZLLOB=ON).
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=ONFor 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=OFFBuild 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) z3Bitwuzla
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.hYices (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 installESBMC is installed into the release folder. Add -DCMAKE_BUILD_TYPE=Debug to
enable ESBMC’s internal assertions.
Using Bitwuzllob
Bitwuzllob (Schreiber, Niemetz, Preiner — TACAS'26) integrates Bitwuzla into
the massively parallel Mallob platform, distributing the bit-blasted SAT
queries across hundreds of cores. Mallob is an MPI program that cannot be
linked into ESBMC, so the --bitwuzllob backend writes the verification
condition to an SMT-LIB2 file and runs Mallob’s one-shot mono mode on it as
an external process. Notes:
- Linux only (Mallob supports x86/ARM Linux). Build Mallob with the SMT
application engine following the artifact of the TACAS'26 paper
(https://doi.org/10.5281/zenodo.17478480), and make sure the
mallobbinary and its MPI runtime are available. - The command is configurable via
--bitwuzllob-prog; every%fis replaced by the formula file (default:mallob -mono=%f -mono-app=SMT). For example:esbmc file.c --bitwuzllob --bitwuzllob-prog "mpirun -np 8 mallob -mono=%f -mono-app=SMT". - A terminated mono process cannot answer model queries, so building a
counterexample additionally needs a local interactive SMT-LIB2 solver via
--bitwuzllob-model-prog(e.g."z3 -in"or"bitwuzla"); it replays the same formula and serves the(get-value ...)queries. Alternatively pass--result-onlyto skip the counterexample. - One-shot mono mode serves a single
(check-sat), so incremental strategies (--incremental-bmc,--k-induction, …) are rejected — use a linked solver such as--bitwuzlafor those. Like Bitwuzla, Bitwuzllob is bit-vector-only and cannot serve--ir/--ir-ieee.
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 buildBuild 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 -dThen 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=1Passing the compiler options for the first time clears the CMake cache, so some variables may need to be re-set.