A tool to compile Noir to LLZK via ACIR.
- Rust (edition 2024)
- LLVM 20 with MLIR support
- zstd (LLVM 20's MLIR libraries depend on libzstd for bitcode compression)
- plc-mlir built locally (for PCL/MLIR libraries)
brew install llvm@20 zstdSet the MLIR prefix path (used by the cmake commands below and by Cargo during build):
export MLIR_SYS_200_PREFIX=$(brew --prefix llvm@20)Clone and build the pcl-mlir component at a known-good commit:
git clone https://github.com/Veridise/pcl-mlir.git
cd pcl-mlir && git checkout 55cf619b032314198aacafc305871fb66b12b70e && cd ..Build with CMake:
cmake -S pcl-mlir -B pcl-mlir/build \
-DCMAKE_BUILD_TYPE=Debug \
-DBUILD_TESTING=OFF \
-DCMAKE_PREFIX_PATH=$MLIR_SYS_200_PREFIX
cmake --build pcl-mlir/buildNote the path to pcl-mlir — you'll need it for the environment variables below.
The LLZK library must be built and installed separately.
The Rust bindings (llzk-rs) expect the LLZK_SYS_10_PREFIX
environment variable to point to the LLZK installation prefix.
Clone at the commit used by the llzk-rs v1 release:
git clone https://github.com/project-llzk/llzk-lib.git
cd llzk-lib && git checkout 030c16eeba535c5592d5cefc564a9101a3e2dc20 && cd ..Build and install with CMake:
cd llzk-lib
cmake -B build -S . \
-DCMAKE_INSTALL_PREFIX=$(pwd)/build/install \
-DCMAKE_PREFIX_PATH=$MLIR_SYS_200_PREFIX
cmake --build build
cmake --install build
cd ..Then set the LLZK_SYS_10_PREFIX environment variable to point to the install location:
export LLZK_SYS_10_PREFIX=$(pwd)/llzk-lib/build/installThe following environment variables must be set before building:
| Variable | Description |
|---|---|
MLIR_SYS_200_PREFIX |
LLVM 20 installation prefix |
TABLEGEN_200_PREFIX |
LLVM 20 installation prefix (same as above) |
LIBCLANG_PATH |
Path to libclang shared library |
LLZK_SYS_10_PREFIX |
Path to the LLZK installation prefix (see above) |
LLZK_PCL_ROOT |
Path to pcl-mlir source directory |
LLZK_PCL_PREFIX |
Path to pcl-mlir/build output directory |
If MLIR's and LLVM's installation is not on standard paths set them here.
For example, for a homebrew version of LLVM on macOS use this path.
export RUSTFLAGS='-L /opt/homebrew/lib/'
This variable may need to be configured on macOS as well. If building fails try setting it.
export LIBCLANG_PATH=$MLIR_SYS_200_PREFIX/lib
cargo buildThe test suite is split by what each layer is meant to validate:
library/src/tests/blackboxes/contains lowering and shape tests for ACIR blackbox opcodes. These check things like witness collection, input validation, helper emission, helper sharing, compute/constrain wiring, and LLZK module verification. They do not execute the generated LLZK.library/src/tests/integration_tests.rscompiles real Noir fixture programs withnargo, translates the resulting ACIR to LLZK, and verifies the module. These tests exercise the full compile/translate pipeline, but still do not execute the generated LLZK.library/src/tests/e2e/blackboxes/contains semantic blackbox tests. These translate ACIR to LLZK and execute the result withllzk_interpreter.library/src/blackboxes/contains the module-level LLZK helper implementations used by both ACIR and Brillig lowering. Tests there build small helper modules and execute them directly withllzk_interpreter.
Use the regular test target for unit, lowering/shape, and Noir fixture integration coverage:
make testUse the e2e target when you need to check emitted LLZK behavior:
make e2e