docs/BUILD.md

Building vllm.cpp

vllm.cpp uses CMake (>= 3.24) and a C++20 compiler (gcc 13/14 and clang are exercised; the tree builds -Werror-clean on gcc 14.2). The text engine uses its own tensor runtime. The default build includes parakeet.cpp for diarization, with its ggml dependency. The OpenAI server uses the vendored header-only HTTP transport cpp-httplib. The README carries the quickstart. This page is the full build reference.

Build out-of-source#

Every recipe on this page configures into a separate build directory, and that is a requirement, not a style preference: the example targets are named after the directories they are built from (examples/tokenize builds tokenize, examples/dump_container builds dump_container, …), so cmake . asks the linker to write each executable on top of its own source directory and fails with cannot open output file <target>: Is a directory (issue #85).

Configure refuses an in-source build up front and says so. If an earlier attempt already wrote into the checkout, clear it with rm -rf CMakeCache.txt CMakeFiles.

CPU build (the correctness / CI reference)#

cmake -S . -B build
cmake --build build -j
ctest --test-dir build

The server is ON by default. Example binaries land under build/examples/: vllm-cli, vllm-server, vllm-bench, and tokenize.

Speaker diarization dependency#

VLLM_CPP_WITH_DIARIZATION defaults to ON. CMake downloads parakeet.cpp at revision 394d270fabb1d6125f05c772aa3ca078a574b19d and builds its library with ggml linked statically. It disables parakeet.cpp’s tests, CLI, and server.

To use an existing checkout at that revision, configure with:

cmake -S . -B build -DVLLM_CPP_PARAKEET_CPP_DIR=/path/to/parakeet.cpp

To omit this dependency, configure with:

cmake -S . -B build -DVLLM_CPP_WITH_DIARIZATION=OFF

The diarization API remains exported but reports that diarization is not compiled in. This option does not disable the text engine or its vt:: runtime.

CUDA build (NVIDIA GB10 / DGX Spark)#

cmake -S . -B build-cuda \
  -DVLLM_CPP_CUDA=ON \
  -DVLLM_CPP_CUTLASS_FETCH=ON
cmake --build build-cuda -j

Triton-AOT cubins for the fast GDN path are vendored: Python and Triton are needed only to regenerate them (VLLM_CPP_TRITON_REGEN), never to build or run them. Because building them needs nothing a CUDA build does not already have, VLLM_CPP_TRITON defaults ON for a CUDA build and the line above no longer carries it; -DVLLM_CPP_TRITON=OFF drops back to the hand C++/CUDA kernels, which stay the always-available fallback.

CUTLASS dependency#

CUTLASS (>= 4.5.0) is a header-only CUDA dependency. It feeds two independent consumers:

  • FlashAttention-2 prefill/decode, on every arch in 8.0 8.6 8.7 8.9 12.0a 12.1a.
  • The sm_12xa NVFP4 block-scaled GEMM, on Blackwell only.

Without it the FA2 kernels are not compiled and attention falls back to the portable path, which is slower. Nothing fails and no test goes red, so it is worth being deliberate about. Pick one:

-DVLLM_CPP_CUTLASS_FETCH=ON            # download CUTLASS 4.5.0 (~200 MB, needs network)
-DVLLM_CPP_CUTLASS_DIR=/path/to/cutlass  # reuse a checkout you already have

The default is neither, so that a disk- or network-constrained box configures without surprises. When you skip it on an arch that supports FA2, configure prints a CMake Warning saying so.

Confirm you got it from the configure output:

-- CUDA feature fa2: ENABLED for [86]
-- FlashAttention-2 prefill/decode: ENABLED for arch(es) [86] (runtime toggles VT_FA2_PREFILL, VT_FA2_DECODE)

The first line means the arch supports FA2; the second means it was actually built. If only the first appears, CUTLASS was not found.

Other CUDA families#

Set the arch explicitly. It defaults to 121a (GB10), which will not load on anything else:

# Hopper H100/H200
cmake -S . -B build-cuda -DVLLM_CPP_CUDA=ON -DVLLM_CPP_CUDA_ARCHITECTURES=90a \
  -DVLLM_CPP_CUTLASS_FETCH=ON

# Ampere consumer (RTX 3090 = 86), Ada (89), Jetson Orin (87)
cmake -S . -B build-cuda -DVLLM_CPP_CUDA=ON -DVLLM_CPP_CUDA_ARCHITECTURES=86 \
  -DVLLM_CPP_CUTLASS_FETCH=ON

Of these, only sm_87 (Orin) and sm_110 (Thor) have been run on real hardware. sm_80/86/89, sm_90a and sm_100a/103a are build-verified: they compile -Werror-clean and emit the expected SASS, but no board here has executed them. See Project status for what that label means and .agents/specs/cuda-arch-ampere-fastpath.md for the per-arch detail. Reports from those boards are welcome.

Metal build (Apple Silicon)#

Metal is detected automatically on an Apple host with an ObjC++ compiler. The optional MLX GEMM provider is a separate opt-in and needs an MLX install:

cmake -S . -B build-metal -DVLLM_CPP_MLX=ON -DMLX_ROOT=/path/to/mlx
cmake --build build-metal -j

MLX is shape-gated to prefill, where it wins; it declines the m < 2 decode GEMV by design. Note that an MLX build produces a different greedy sequence than the default build (MLX’s GEMM is not bit-identical), so goldens must not be re-anchored to an MLX build. Details in docs/BENCHMARKS.md .

Vulkan build#

Headers are vendored and SPIR-V is committed, so no graphics toolchain is needed. It is off unless requested:

cmake -S . -B build-vulkan -DVLLM_CPP_VULKAN=ON
cmake --build build-vulkan -j

This build includes the ternary kernels . The GGUF reader does not yet load TQ1_0 or TQ2_0 tensors.

Tenstorrent build (Blackhole)#

The Tenstorrent backend is opt-in and requires local TT-Metalium and TT-NN package installations. Point CMAKE_PREFIX_PATH at the built tt-metal install tree. Configure fails instead of silently producing a CPU-only build when either package is missing.

cmake -S . -B build-tenstorrent \
  -DVLLM_CPP_TENSTORRENT=ON \
  -DCMAKE_PREFIX_PATH=/path/to/tt-metal/install
cmake --build build-tenstorrent -j

The Blackhole lane is correctness-focused. OPT-125m passes its strict 6/6 end-to-end gate. Qwen3-0.6B is selected by the platform and has a device-aware near-tie gate plus committed goldens, but the full 16x16 rerun is still pending. The capture A/B measures Qwen3-0.6B against this engine’s capture-disabled path. It does not compare reference engines.

Quantized Qwen smoke runs#

Qwen3.8-27B and Qwen3.5-0.8B Q4_K_M completed two prompts each on a Blackhole P150. These runs use the opt-in int8-dot path, which computes from compressed weights. The int8-dot path is the DEFAULT; it computes from compressed weights. Set VT_TT_KEEPQUANT_INT8DOT=0 to opt out to the legacy grouped dequant path. Unset or empty keeps the int8-dot default on.

After configuring the TT-Metal runtime environment, run this smoke workload with a local checkpoint:

build-tenstorrent/examples/vllm-bench \
  --model /path/to/Qwen3.8-27B-Q4_K_M.gguf \
  --num-prompts 2 --input-len 128 --output-len 32 --concurrency 2 \
  --num-blocks 64 --max-num-batched-tokens 64 --seed 0

The smoke measurements establish completion only, without a token comparison or reference-engine speed result. The keep-quant record describes the separate correctness gates and remaining work.

ROCm build (AMD GPUs)#

Enable ROCm explicitly and use a release build:

cmake -S . -B build-hip \
  -DVLLM_CPP_HIP=ON \
  -DCMAKE_BUILD_TYPE=Release \
  -DROCM_PATH=/opt/rocm
cmake --build build-hip -j
ctest --test-dir build-hip -R 'rocm|cross_device' --output-on-failure

Set ROCM_PATH to your ROCm or TheRock installation prefix. When that directory exists, CMake derives the compiler root, HIP flags, and environment hint from it. Explicit CMAKE_HIP_COMPILER_ROCM_ROOT, CMAKE_HIP_FLAGS, HIPFLAGS, and ROCM_PATH environment settings take precedence over the corresponding hints. Configuration fails if VLLM_CPP_HIP=ON cannot find a HIP compiler.

Set VLLM_CPP_HIP_ARCHITECTURES to select targets, for example -DVLLM_CPP_HIP_ARCHITECTURES=gfx1100. Leave it empty to use the compiler’s default target selection. CMake warns about unlisted architectures but passes them to the compiler.

For an empty build type or Debug, CMake adds -O1 to HIP device compilation unless CMAKE_HIP_FLAGS contains an explicit -O option. This avoids the unoptimized kernel path associated with a ROCm teardown deadlock (#132 ). Other build types keep their own optimization settings.

The backend includes native dense, attention, GDN, sampling, and EXL3 operations. Llama-3.2-1B-Instruct EXL3 generated on gfx1151 with zero CPU fallbacks. That result does not establish discrete AMD coverage or competitive performance. The EXL3 evidence records the workload and remaining gates.

CPU fallback depends on the device’s memory attributes. By default, gfx1151 and gfx1103 use plain hipMalloc and require native coverage for every model operation. See the ROCm guide for allocation behavior, device selection, tested models, and unresolved correctness gates.

Nix shells#

The checked-in flake pins CMake, Ninja and the CUDA toolchain, so nothing has to be globally installed:

# CPU (correctness / CI reference)
nix develop .#default --command cmake -S . -B build-nix-cpu -G Ninja \
  -DVLLM_CPP_CUDA=OFF -DCMAKE_BUILD_TYPE=RelWithDebInfo
nix develop .#default --command cmake --build build-nix-cpu -j4

# CUDA (set the arch for your GPU)
nix develop .#cuda --command bash -lc \
  'cmake -S . -B build-nix-cuda -G Ninja -DVLLM_CPP_CUDA=ON \
    -DCMAKE_CUDA_COMPILER="$CMAKE_CUDA_COMPILER" \
    -DCMAKE_CUDA_HOST_COMPILER="$CMAKE_CUDA_HOST_COMPILER" \
    -DVLLM_CPP_CUDA_ARCHITECTURES=120a -DCMAKE_BUILD_TYPE=RelWithDebInfo'
nix develop .#cuda --command cmake --build build-nix-cuda -j4

On NixOS the CUDA shell exports the driver-library path and TRITON_LIBCUDA_PATH=/run/opengl-driver/lib so Triton finds libcuda without /sbin/ldconfig.

CMake options#

Read from CMakeLists.txt . Defaults shown are the shipped defaults.

OptionDefaultPurpose
VLLM_CPP_CUDAAUTOBuild the CUDA backend: ON, OFF, or AUTO (on when a CUDA toolchain is found)
VLLM_CPP_CUDA_ARCHITECTURES121aTarget CUDA arch(s): 121a (GB10), 120a/120a;121a (consumer Blackwell), and cross-family targets 90a, 80/86/87/89, 100a/103a, 110. The a suffix is required for the native fp4 MMA
VLLM_CPP_METALAUTOBuild the Metal backend: ON, OFF, or AUTO (on for an Apple host with an ObjC++ compiler)
VLLM_CPP_VULKANAUTO (= OFF)Build the Vulkan backend. Opt-in with -DVLLM_CPP_VULKAN=ON; headers are vendored and SPIR-V is committed
VLLM_CPP_TENSTORRENTAUTO (= OFF)Build the Tenstorrent backend. Opt-in with -DVLLM_CPP_TENSTORRENT=ON; requires TT-Metalium and TT-NN and fails configure if either package is missing
VLLM_CPP_HIPAUTO (= OFF)Build the ROCm backend. Opt-in with -DVLLM_CPP_HIP=ON. Configuration fails without a HIP compiler. See ROCm coverage
VLLM_CPP_HIP_ARCHITECTURES(empty)Target gfx architectures, for example gfx1100 or gfx1100;gfx1151. Empty uses compiler defaults
ROCM_PATH/opt/rocmROCm installation prefix, for a nightly/TheRock install elsewhere
VLLM_CPP_MLXOFFBuild the optional MLX GEMM provider for Metal (needs -DMLX_ROOT=<mlx install>)
MLX_ROOT(empty)Root of an MLX install (include/ + lib/) for VLLM_CPP_MLX
VLLM_CPP_SERVERONBuild the OpenAI HTTP server (needs third_party/httplib/httplib.h; disables itself with a warning if absent)
VLLM_CPP_TRITONcomputed: ON for a CUDA build with the vendored trees present, else OFFConsume the vendored per-arch Triton-AOT GDN cubins (CUDA only; no Python needed). It ships ON because the artifacts are pre-generated cubins embedded in plain C — a C compiler is the whole requirement. It declines, with one STATUS line naming the condition, when VLLM_CPP_CUDA is OFF, when VLLM_CPP_TRITON_REGEN is ON, or when a vendored tree is absent, incomplete, or older than the triton_kernels/*.py it was generated from — the same conditions the build itself refuses to consume, checked before the default is set so it can decline instead of failing your configure. Turn it off with -DVLLM_CPP_TRITON=OFF
VLLM_CPP_TRITON_REGENOFFMaintainer knob: regenerate the AOT cubins with Python + Triton
VLLM_CPP_CUTLASS_DIRthird_party/cutlassCUTLASS source root (>= 4.5.0). Feeds the sm120a NVFP4 GEMM and FlashAttention-2 on 8.0/8.6/8.7/8.9/12.0a/12.1a. Absent on an FA2-capable arch, configure warns and FA2 is not built
VLLM_CPP_CUTLASS_FETCHOFFFetchContent CUTLASS 4.5.0 if not found locally (~200 MB, needs network)
VLLM_CPP_MARLINONBuild the vendored Marlin NVFP4 W4A16 MoE GEMM (sm_12xa)
VLLM_CPP_BUILD_TESTSONCompile and register ctest targets
VLLM_CPP_BUILD_EXAMPLESONBuild the example CLI, server, and bench binaries
VLLM_CPP_BENCH_PROFILE_CONTROLOFFTrace-only profiler replay control (never for production timing builds)

Build success does not imply runtime coverage. See Features for the current backend and quantization support table. See Status for lifecycle state and Benchmarks for measured results.

Runtime environment variables are in the environment-variable reference .