C++ Tooling#
This guide covers the TVM-FFI C++ toolchain: header layout, build integration, library distribution, and editor setup. For an end-to-end walkthrough that builds, loads, and calls a C++/CUDA kernel, see Quick Start.
Prerequisite
Compiler: C++17-capable toolchain (GCC/Clang/MSVC)
CMake: 3.18 or newer
TVM-FFI installed via
pip install --reinstall --upgrade apache-tvm-ffi
C++ Headers#
Core APIs. A single umbrella header exposes most of the API surface, including functions, objects, Any/AnyView, tensors, and exception handling.
#include <tvm/ffi/tvm_ffi.h>
Extra features live in dedicated headers under tvm/ffi/extra/ and should be included only when needed:
Environment API – allocator, stream, and device access (see Tensor and DLPack for usage):
#include <tvm/ffi/extra/c_env_api.h>Dynamic module loading (see Modules):
#include <tvm/ffi/extra/module.h>CUBIN launcher (see CUBIN Launcher Guide):
#include <tvm/ffi/extra/cuda/cubin_launcher.h>
Build with TVM-FFI#
CMake#
TVM-FFI ships CMake utilities and imported targets through its package configuration.
The two primary functions are tvm_ffi_configure_target and tvm_ffi_install,
both defined in cmake/Utils/Library.cmake.
Hint
See examples/python_packaging/CMakeLists.txt for a complete working example.
Configure Target#
tvm_ffi_configure_target wires a CMake target to TVM-FFI with sensible
defaults: it links headers and the shared library, configures debug symbols,
and optionally runs stub generation as a post-build step.
tvm_ffi_configure_target(
<target>
[LINK_SHARED ON|OFF ]
[LINK_HEADER ON|OFF ]
[DEBUG_SYMBOL ON|OFF ]
[MSVC_FLAGS ON|OFF ]
[STUB_INIT ON|OFF ]
[STUB_DIR <dir> ]
[STUB_PKG <pkg> ]
[STUB_PREFIX <prefix>]
)
- LINK_SHARED:
(default: ON) Link against the TVM-FFI shared library
tvm_ffi::shared. Set OFF for header-only usage or deferred runtime loading.- LINK_HEADER:
(default: ON) Link against the TVM-FFI headers via
tvm_ffi::header. Set OFF when you manage include paths and compile definitions manually.- DEBUG_SYMBOL:
(default: ON) Enable debug symbol post-processing hooks. On Apple platforms this runs
dsymutil.- MSVC_FLAGS:
(default: ON) Apply MSVC compatibility flags.
- STUB_DIR:
(default: “”) Output directory for generated Python stubs. When set, stub generation runs as a post-build step.
- STUB_INIT:
(default: OFF) Allow the stub generator to initialize a new package layout. Requires
STUB_DIR.- STUB_PKG:
(default: “”) Package name passed to the stub generator. Requires
STUB_DIRandSTUB_INIT=ON.- STUB_PREFIX:
(default: “”) Module prefix passed to the stub generator. Requires
STUB_DIRandSTUB_INIT=ON.
See CMake-based Generation for a detailed explanation of each STUB_* option
and the generation modes they control.
Install Target#
tvm_ffi_install installs platform-specific artifacts for a target.
On Apple platforms it installs the .dSYM bundle when present;
on other platforms this is currently a no-op.
tvm_ffi_install(
<target>
[DESTINATION <dir>]
)
- DESTINATION:
Install destination directory relative to
CMAKE_INSTALL_PREFIX.
Set tvm_ffi_ROOT#
If find_package(tvm_ffi CONFIG REQUIRED) fails because CMake cannot locate
the package, pass tvm_ffi_ROOT explicitly:
cmake -S . -B build \
-Dtvm_ffi_ROOT="$(tvm-ffi-config --cmakedir)"
Note
When packaging Python wheels with scikit-build-core, tvm_ffi_ROOT is
discovered automatically from the active Python environment.
GCC/NVCC#
For quick prototyping or CI scripts without CMake, invoke g++ or nvcc
directly with flags from tvm-ffi-config.
The examples below are from the Quick Start tutorial:
g++ -shared -O3 compile/add_one_cpu.cc \
-fPIC -fvisibility=hidden \
$(tvm-ffi-config --cxxflags) \
$(tvm-ffi-config --ldflags) \
$(tvm-ffi-config --libs) \
-o $BUILD_DIR/add_one_cpu.so
nvcc -shared -O3 compile/add_one_cuda.cu \
-Xcompiler -fPIC,-fvisibility=hidden \
$(tvm-ffi-config --cxxflags) \
$(tvm-ffi-config --ldflags) \
$(tvm-ffi-config --libs) \
-o $BUILD_DIR/add_one_cuda.so
The three tvm-ffi-config flags provide:
--cxxflags:Include paths and compile definitions (
-I...,-D...)--ldflags:Library search paths (
-L...,-Wl,-rpath,...)--libs:Libraries to link (
-ltvm_ffi)
RPATH handling. The resulting shared library links against libtvm_ffi.so,
so the dynamic linker must be able to find it at load time:
Python distribution.
import tvm_ffipreloadslibtvm_ffi.sointo the process before any user library is loaded, so the RPATH requirement is already satisfied without additional linker flags.Pure C++ distribution. You must ensure
libtvm_ffi.sois on the library search path. Either set-Wl,-rpath,$(tvm-ffi-config --libdir)at link time, or placelibtvm_ffi.soalongside your binary.
Library Distribution#
When distributing pre-built shared libraries on Linux, glibc symbol versioning can cause load-time failures on systems with a different glibc version. The standard solution is the manylinux approach: build on old glibc, run on new.
Build environment. Use a manylinux Docker image:
docker pull quay.io/pypa/manylinux2014_x86_64
Build host and device code inside the container. For CUDA:
nvcc -shared -Xcompiler -fPIC your_kernel.cu -o kernel.so \
$(tvm-ffi-config --cxxflags) \
$(tvm-ffi-config --ldflags) \
$(tvm-ffi-config --libs)
Verify glibc requirements. Inspect the minimum glibc version your binary requires:
objdump -T your_kernel.so | grep GLIBC_
The apache-tvm-ffi wheel is already manylinux-compatible, so linking against
it inside a manylinux build environment produces portable binaries.
Editor Setup#
The following configuration enables code completion and diagnostics in VSCode, Cursor, or any editor backed by clangd.
CMake Tools (VSCode/Cursor). Add these workspace settings so CMake Tools
can locate TVM-FFI and generate compile_commands.json:
{
"cmake.buildDirectory": "${workspaceFolder}/build-vscode",
"cmake.configureArgs": [
"-DCMAKE_EXPORT_COMPILE_COMMANDS=ON"
],
"cmake.configureSettings": {
"Python_EXECUTABLE": "${workspaceFolder}/.venv/bin/python3",
"tvm_ffi_ROOT": "${workspaceFolder}/.venv/lib/pythonX.Y/site-packages/tvm_ffi/share/cmake/tvm_ffi"
}
}
Important
Make sure Python_EXECUTABLE and tvm_ffi_ROOT match the virtual
environment you intend to use.
clangd. Create a .clangd file at the project root pointing to the CMake
compilation database. The snippet below also strips NVCC flags that clangd
does not recognize:
CompileFlags:
CompilationDatabase: build-vscode/
Remove: # for NVCC compatibility
- -forward-unknown-to-host-compiler
- --generate-code*
- -Xcompiler*
Further Reading#
Quick Start: End-to-end walkthrough building and shipping a C++/CUDA kernel
Stub Generation: Generating Python type stubs from C++ reflection metadata
Python Packaging: Packaging shared libraries as Python wheels
Function and Module: Defining and exporting TVM-FFI functions
Object and Class: Defining C++ classes with cross-language reflection
Exception Handling: Error handling across language boundaries
ABI Overview: Low-level C ABI details