This guide explains how to build, test, and lint ONNX Runtime GenAI from source. It is written to be quick to skim for humans and unambiguous for AI coding agents: every section lists the exact command to run.
For end-user install instructions (pip / NuGet), see the README and the official docs.
For the current continuous-batching architecture and transactional paged KV-cache flow, see Paged Attention Engine. The performance and design history behind the batching implementation is documented separately in Engine Batching Design.
| Tool | Notes |
|---|---|
| Python ≥ 3.10 | Drives build.py; also the runtime for the Python wheel. Official wheels target 3.11–3.14. |
| CMake ≥ 3.26 | Build-system generator. macOS builds require CMake ≥ 3.28. |
| C++ compiler with C++20 support | MSVC (Visual Studio 2022), GCC ≥ 11, or Clang. |
| Git | For cloning the repository. |
| .NET SDK ≥ 8 | Only for the C# bindings (--build_csharp). |
| JDK ≥ 8 | Only for the Java bindings (--build_java). The repository includes the Gradle wrapper, so a separate Gradle installation is not required. |
| CUDA Toolkit | Only for CUDA builds (--use_cuda). |
Clone the repository:
git clone https://github.com/microsoft/onnxruntime-genai.git
cd onnxruntime-genaiThis repository has no git submodules. CMake-managed native dependencies are fetched automatically at configure time (via
FetchContent, driven bycmake/deps.txt), so no submodule initialization is needed. Python, Rust, and Java dependencies use their respective package managers.
Install the common Python build-time dependencies. pybind11 is required when building the Python SDK incrementally with --sdk python:
python -m pip install -r requirements-dev.txtbuild.py is the single cross-platform entry point. build.sh (Linux/macOS) and build.bat (Windows) are thin wrappers around it.
Build the CPU native library, Python wheel, C examples, and native tests with the default RelWithDebInfo configuration:
python build.pyCommon everyday build (RelWithDebInfo, parallel, skip tests and examples for a fast inner loop):
python build.py --config RelWithDebInfo --parallel --skip_tests --skip_examplesThe Python wheel is built by default. The build tree is created under build/<platform>/<config>/ (for example, build/Windows/RelWithDebInfo/ or build/Linux/RelWithDebInfo/). With a multi-config generator such as Visual Studio, native binaries are in an additional configuration subdirectory such as build/Windows/RelWithDebInfo/RelWithDebInfo/.
build.py runs three phases. If no phase is specified, it requests all three (--update --build --test). For --arm64 and --arm64ec cross-compilation, the test phase is disabled after CMake configuration because the target binaries cannot run on the host. If you pass any phase explicitly, only those phases run.
| Phase flag | What it does |
|---|---|
--update |
Run CMake to (re)generate the build system. |
--build |
Compile all targets. |
--test |
Run the unit tests. |
Example — regenerate CMake, then build, without running tests:
python build.py --update --buildExample — rebuild only (skip CMake regeneration and tests), useful after editing source files:
python build.py --buildFrequently used flags:
| Flag | Purpose |
|---|---|
--config {Debug,Release,RelWithDebInfo,MinSizeRel} |
Build configuration. Default RelWithDebInfo. |
--parallel |
Parallel compilation. |
--skip_tests |
Skip the test phase. |
--skip_wheel |
Do not build the Python wheel. |
--skip_examples |
Do not build the sample executables. |
--build_dir <path> |
Override the build directory (default build/<platform>). |
--use_guidance |
Enable constrained / grammar-based decoding (guidance). |
--ort_home <path> |
Use a prebuilt ONNX Runtime at this path instead of auto-downloading. |
--cmake_extra_defines K=V |
Pass extra -DK=V options to CMake. |
Run python build.py --help for the complete list.
By default the build targets the CPU execution provider. Enable hardware acceleration with these flags:
# CUDA (reads CUDA_HOME / CUDA_PATH, or pass --cuda_home)
python build.py --use_cuda --config RelWithDebInfo
# DirectML (Windows)
python build.py --use_dml --config RelWithDebInfo
# WinML (Windows; bundles CUDA + DirectML). --winml_sdk_version is optional.
python build.py --use_winml --winml_sdk_version 2.1.1 --config RelWithDebInfoThe Python wheel is built by default. Enable the others explicitly:
# C# (requires the .NET SDK)
python build.py --build_csharp --config RelWithDebInfo
# Java (requires a JDK; uses the repository's Gradle wrapper)
python build.py --build_java --config RelWithDebInfoTo skip the Python wheel (e.g. when you only want the native library or C#):
python build.py --skip_wheel --build_csharpThe packaging pipeline builds the native core once, installs it, then builds each SDK layer (Python / C# / Java) against that prebuilt core. You can use the same flow locally to iterate on a single binding without rebuilding the core.
Step 1 — build and install only the core to a prefix:
python build.py --config RelWithDebInfo --parallel --skip_tests --skip_examples --skip_wheel --ort_home /path/to/ort --install_dir /path/to/core-install --cmake_extra_defines ENABLE_PYTHON=OFF ENABLE_TESTS=OFFStep 2 — build a single SDK against the installed core (the core is not rebuilt):
python build.py --sdk python --prebuilt_genai_home /path/to/core-install --ort_home /path/to/ort --config RelWithDebInfo--sdk accepts python, java, or csharp. Both --prebuilt_genai_home and --ort_home are required in SDK mode.
The core install prefix, including the native CPack archive, uses this layout:
<prefix>/include/ # Public C and C++ headers
<prefix>/lib/ # Native GenAI libraries
<prefix>/lib/cmake/onnxruntime-genai/ # CMake package configuration
Use the exported CMake package from a native consumer:
find_package(onnxruntime-genai CONFIG REQUIRED)
target_link_libraries(my_app PRIVATE onnxruntime-genai::onnxruntime-genai)Configure the consumer with -Donnxruntime-genai_DIR=<prefix>/lib/cmake/onnxruntime-genai.
ONNX Runtime is an external runtime dependency and is not included in the core archive.
After a build, run the native tests from the build directory:
ctest --test-dir build/<platform>/<config> --build-config <config> --output-on-failureExample:
ctest --test-dir build/Windows/RelWithDebInfo --build-config RelWithDebInfo --output-on-failureYou can also let build.py run them as part of the --test phase:
python build.py --config RelWithDebInfo --testNote:
build.pyautomatically disables the native test phase for--arm64and--arm64ec. Android and iOS disable CMake unit-test targets during configuration; Android emulator tests are available only for an x86-64 Android build with--build_java --android_run_emulator.
Install the Python test dependencies and the wheel produced by your build:
python -m pip install -r test/python/requirements.txt
python -m pip install --force-reinstall <path-to-built-wheel>The Python tests require model files. From the repository root, point pytest at a models directory with --test_models:
python -m pytest -sv test/python/test_onnxruntime_genai_api.py -k "test_greedy_search" --test_models test/modelsDrop the -k filter to run the whole file. See test/python/README.md. Provider-specific tests may require additional dependency files under test/python/<provider>/.
This project uses lintrunner. Install and initialize once:
pip install -r requirements-lintrunner.txt
lintrunner initThen, to auto-format your local (changed) files:
lintrunner -aTo format the entire tree:
lintrunner -a --all-filesCI gate: C/C++ formatting is enforced with clang-format 20.1.0 (
--dry-run -Werror). Any unformatted changed C/C++ file fails the PR, so runlintrunner -abefore pushing.
# Windows ARM64 (cross-compiled on an x64 host)
python build.py --arm64 --config RelWithDebInfo --skip_tests
# Android (requires ANDROID_HOME / ANDROID_NDK_HOME)
python build.py --android --android_abi arm64-v8a --config RelWithDebInfo --skip_tests
# iOS simulator framework (build on macOS)
python build.py --ios --build_apple_framework --apple_sysroot iphonesimulator --osx_arch arm64 --apple_deploy_target 15.4 --cmake_generator Xcode --config RelWithDebInfo --skip_tests --skip_wheelFor a physical iOS device, use --apple_sysroot iphoneos. Cross-compiled targets cannot run native CTest binaries on the build host, so pass --skip_tests explicitly unless you are using the supported Android emulator-test flow.
| Path | Contents |
|---|---|
src/ |
Core C++ implementation (models, engine, generators, search/sampling, KV cache). |
src/python/ |
Python binding (pybind11) + wheel packaging. |
src/csharp/ |
C# binding. |
src/java/ |
Java binding (Gradle). |
src/objectivec/ |
Objective-C binding. |
cmake/ |
CMake modules (options, ORT resolution, packaging, telemetry) and deps.txt (fetched dependencies). |
test/ |
C++ (test/*.cpp) and Python (test/python/) tests; test models in test/models/. |
examples/ |
Runnable samples (C, C#, Python). |
.pipelines/ |
Azure DevOps packaging pipeline (stages, jobs, steps). |
build.py |
Cross-platform build driver. |
VERSION_INFO |
Package version (e.g. 0.15.0-dev). |
- Dependency fetch errors during CMake configure — dependencies are downloaded via
FetchContent(cmake/deps.txt); ensure network access to the declared URLs, then re-run with--update. - Missing Python build dependency — run
python -m pip install -r requirements-dev.txt. - Stale CMake cache after switching flags (e.g. adding
--arm64) — delete the build directory (orCMakeCache.txtinside it) and re-run with--update. onnxruntime.lib/ ORT not found — pass--ort_home <path>to point at a prebuilt ONNX Runtime, or omit it to letbuild.pyauto-download a matching build.- Clean an existing build —
python build.py --clean --skip_examplesruns the CMakecleantarget for the selected configuration; it does not rebuild. Run a normalpython build.pycommand afterward, or delete the build directory for a completely fresh configure.