# Installation

Guillotine is a Zig library with vendored C and Rust dependencies. There is no
package to `npm install` for the core engine — you build it, or you consume one
of the [language bindings](/guides/bindings).

## Prerequisites

| Requirement | Version used to verify these docs | Why |
| --- | --- | --- |
| [Zig](https://ziglang.org/download/) | `0.15.2` | The whole engine. `build.zig.zon` declares `minimum_zig_version = "0.15.1"`. |
| [Rust / Cargo](https://rustup.rs) | stable | `lib/voltaire` builds a `crypto_wrappers` staticlib (arkworks BN254/BLS12-381 + keccak) that the Zig build links. |
| A C/C++ toolchain | Apple Clang 17 (Xcode CLT) | `blst`, `c-kzg-4844` and `libc++` linkage. |
| Python 3 | 3.11+ | Only for `zig build test-mini-full` and some spec-fixture tooling. Not needed for a normal build. |

Check what you have:

```bash
zig version
# 0.15.2

cargo --version
# cargo 1.x.y

cc --version
```

:::tip
Zig releases are not backwards compatible at this stage of the language. Pin
`0.15.x` — [zvm](https://github.com/tristanisham/zvm) or
[asdf](https://github.com/asdf-community/asdf-zig) make that painless. `0.16`
and `0.14` will not compile this tree.
:::

## Platform support

Verified on this machine: **macOS 15 (Darwin 25.2.0), arm64**.

| Platform | Status |
| --- | --- |
| macOS arm64 | Verified — `zig build` succeeds |
| macOS x86\_64 | Expected to work; same code paths, not verified here |
| Linux x86\_64 / arm64 | Supported by the build graph and exercised in CI (`.github/workflows/ci.yml`); not verified on this machine |
| Windows | `build.zig` forces the `*-pc-windows-gnu` Rust triple so Cargo emits `lib*.a` instead of MSVC `*.lib`. Treat as best-effort. |
| `wasm32-freestanding` | First-class target: `zig build wasm` and `zig build wasm-minimal-evm`. The Rust crypto crate is rebuilt with `--no-default-features --features portable` (pure-Rust keccak) for WASM. |

## Clone and build

```bash
git clone https://github.com/evmts/guillotine
cd guillotine
zig build
```

Real output from a successful run on macOS arm64 (Zig only prints on failure, so
a silent exit 0 is the success case):

```
$ zig build ; echo "exit=$?"
+ cc -O2 -fno-builtin -fPIC -Wall -Wextra -Werror -c ./src/server.c
+ cc -O2 -fno-builtin -fPIC -Wall -Wextra -Werror -c ./build/assembly.S
+ ar rc libblst.a assembly.o server.o
+ ranlib libblst.a
exit=0
```

The first build is slow — it compiles `blst`, `c-kzg-4844`, the arkworks Rust
crate, and the Foundry compiler wrapper. Expect several minutes. Subsequent
builds hit the Zig and Cargo caches.

### Build options

`build.zig` exposes the engine's comptime configuration as build flags, so you
can specialise the binary without writing Zig:

```bash
# Release modes
zig build --release=fast
zig build --release=small
zig build --release=safe

# Target a specific hardfork (default: CANCUN)
zig build -Devm-hardfork=SHANGHAI

# Toggle engine features
zig build -Devm-enable-fusion=false
zig build -Devm-disable-gas=true      # testing only
zig build -Dno_precompiles=true       # minimal build
zig build -Devm-optimize=small        # fast | small | safe
```

Accepted hardforks: `FRONTIER`, `HOMESTEAD`, `BYZANTIUM`, `BERLIN`, `LONDON`,
`SHANGHAI`, `CANCUN`.

## Running the tests

```bash
zig build test              # specs -> integration -> unit
zig build test-unit         # src/**/*.zig
zig build test-integration  # test/**/*.zig
zig build test-lib          # lib/**/*.zig
zig build test-opcodes      # per-opcode differential tests vs MinimalEvm
zig build specs             # Ethereum execution-spec tests
```

Filter with `-Dtest-filter`:

```bash
zig build test-opcodes -Dtest-filter='ADD opcode'
zig build test-integration -Dtest-filter='differential'
```

:::info[Zig tests are silent when they pass]
A passing `zig build test-*` prints nothing but the build summary. No output is
success, not a hung run.
:::

## Known build friction

These are real, reproduced on a clean checkout — not hypotheticals.

**`lib/voltaire` is neither a workspace member nor excluded.** The root
`Cargo.toml` declares `members = ["lib/foundry-compilers", "lib/ark"]` and
`exclude = ["bench/evm-bench", "benchmarks"]`. `lib/voltaire/Cargo.toml` has no
`[workspace]` table of its own, so Cargo refuses to build it:

```
$ cd lib/voltaire && cargo build --release
error: current package believes it's in a workspace when it's not:
current:   /…/guillotine/lib/voltaire/Cargo.toml
workspace: /…/guillotine/Cargo.toml
```

Until that is fixed upstream, add `"lib/voltaire"` to the root `exclude` array
(or to `members`) and build the staticlib once:

```bash
cargo build --release --manifest-path lib/voltaire/Cargo.toml
ls -l lib/voltaire/target/release/libcrypto_wrappers.a
```

Without that archive, `zig build test-integration` fails at link time with
`libcrypto_wrappers.a: file not found`, even though plain `zig build` succeeds.

**Cargo profile warning.** Every build prints:

```
warning: profiles for the non root package will be ignored, specify profiles at the workspace root:
package:   …/lib/foundry-compilers/Cargo.toml
workspace: …/Cargo.toml
```

Harmless — `lib/foundry-compilers` defines `[profile.*]` that only the workspace
root may set.
