Build Guide¶
This guide contains the detailed build setup for KangEngine. The root README keeps only the short path; use this document when setting up a new machine or enabling optional components.
Requirements¶
CMake
Ninja or a compatible build tool
A C++17 compiler
vcpkg
PhysX under
$HOME/Physics/PhysX(5.1 CPU compatibility or 5.8 GPU)Python 3.12 for Python bindings
vcpkg¶
KangEngine uses vcpkg manifest mode for most third-party C++ dependencies.
Clone and bootstrap vcpkg.
git clone https://github.com/microsoft/vcpkg.git cd vcpkg && ./bootstrap-vcpkg.sh
Export
VCPKG_ROOTand add vcpkg toPATH.export VCPKG_ROOT=/path/to/vcpkg export PATH=$VCPKG_ROOT:$PATH
Linux¶
Tested with Ubuntu 24.04.
Install system packages.
sudo apt install clang ninja-build unzip libxinerama-dev libxcursor-dev xorg-dev libglu1-mesa-dev pkg-config autoconf autoconf-archive automake libtool
Choose and build one PhysX configuration.
CPU build — PhysX 5.1.2
Download NVIDIA Omniverse PhysX under $HOME/Physics/PhysX.
mkdir -p ~/Physics
cd ~/Physics
wget https://github.com/NVIDIA-Omniverse/PhysX/archive/refs/tags/104.1-physx-5.1.2.zip
unzip 104.1-physx-5.1.2.zip
mv PhysX-104.1-physx-5.1.2 PhysX
Build it with clang.
cd ~/Physics/PhysX/physx
./buildtools/packman/packman update -y
./generate_projects.sh
cd compiler/linux-release
cmake . \
-DCMAKE_C_COMPILER=clang \
-DCMAKE_CXX_COMPILER=clang++ \
-DCMAKE_CXX_FLAGS="-Wno-error=unsafe-buffer-usage -Wno-unsafe-buffer-usage -Wno-error=switch-default -Wno-switch-default -Wno-error=invalid-offsetof -Wno-invalid-offsetof -Wno-error=unused-but-set-variable -Wno-unused-but-set-variable"
cmake --build . --config release
KangEngine uses the libraries in
~/Physics/PhysX/physx/bin/linux.clang/release. PhysX snippet executables may
fail to link against their bundled OpenGL package; KangEngine does not require
those executables.
GPU build — PhysX 5.8
Clone the NVIDIA Omniverse PhysX
110.0-omni-and-physx-5.8.0
tag under $HOME/Physics/PhysX.
mkdir -p ~/Physics
cd ~/Physics
git clone \
--branch 110.0-omni-and-physx-5.8.0 \
--depth 1 \
https://github.com/NVIDIA-Omniverse/PhysX.git \
PhysX
Follow PhysX’s official
README_LINUX.md
to install its Linux prerequisites and generate the build. Enable the PhysX GPU
projects and produce a release build under linux.x86_64.
KangEngine’s CUDA targets select that output through:
PHYSX_CUDA_BIN_PLATFORM=linux.x86_64
The expected GPU shared library is:
$HOME/Physics/PhysX/physx/bin/linux.x86_64/release/libPhysXGpu_64.so
PhysX 5.8 supports CUDA 12.8 directly. Building it with CUDA 13 requires the
compatibility patch below; the sm_89 verification applies to RTX 4090 and
other Ada targets.
CUDA 13 / RTX 4090 compatibility¶
PhysX 5.8 architecture and CUDA Driver API patches
TL;DR¶
For PhysX 5.8, CUDA 13, and RTX 4090:
export PHYSX_ROOT=$HOME/Physics/PhysX/physx
export PHYSX_BUILD=$PHYSX_ROOT/compiler/linux-clang-release-5.8
export PHYSX_CUDA_SOURCE=$PHYSX_ROOT/source/cudamanager/src/CudaContextManager.cpp
python3 - "$PHYSX_CUDA_SOURCE" <<'PY'
from pathlib import Path
import sys
path = Path(sys.argv[1])
source = path.read_text()
old = "status = cuCtxCreate(&mCtx, (unsigned int)flags, mDevHandle);"
new = """#if CUDA_VERSION >= 13000
CUctxCreateParams ctxCreateParams = {};
status = cuCtxCreate(&mCtx, &ctxCreateParams, (unsigned int)flags, mDevHandle);
#else
status = cuCtxCreate(&mCtx, (unsigned int)flags, mDevHandle);
#endif"""
if new not in source:
if old not in source:
raise SystemExit("cuCtxCreate call not found; inspect the PhysX source")
path.write_text(source.replace(old, new, 1))
PY
cmake -S $PHYSX_ROOT/compiler/public \
-B $PHYSX_BUILD \
-DPHYSX_ROOT_DIR=$PHYSX_ROOT \
-DTARGET_BUILD_PLATFORM=linux \
-DCMAKE_BUILD_TYPE=release \
-DPX_OUTPUT_LIB_DIR=$PHYSX_ROOT \
-DPX_OUTPUT_BIN_DIR=$PHYSX_ROOT \
-DPX_GENERATE_STATIC_LIBRARIES=ON \
-DPX_GENERATE_GPU_PROJECTS=ON \
-DPX_GENERATE_GPU_REDUCED_ARCHITECTURES=ON
rg 'ARCH_CODE_LIST' $PHYSX_BUILD/CMakeCache.txt
cmake --build $PHYSX_BUILD --parallel
/usr/local/cuda/bin/cuobjdump --list-elf \
$PHYSX_ROOT/bin/linux.x86_64/release/libPhysXGpu_64.so \
| rg 'sm_89'
Why these flags and patches are needed
These notes document the Linux build that produced a PhysX 5.8.0 GPU library
with native sm_89 cubins for RTX 4090. Use this path when the older PhysX
5.1 GPU binary reports PhysX internal CUDA kernel launch failures on Ada GPUs.
The examples below assume the PhysX checkout lives at:
$HOME/Physics/PhysX
The build directory name is not special. Use any clean directory outside older PhysX build trees; this document uses:
$HOME/Physics/PhysX/physx/compiler/linux-clang-release-5.8
CUDA 13 architecture fix¶
CUDA 13.0 nvcc no longer accepts compute_70. PhysX 5.8.0’s default GPU
architecture list includes it unless reduced GPU architectures are enabled.
Configure with PX_GENERATE_GPU_REDUCED_ARCHITECTURES=ON so the generated
ARCH_CODE_LIST starts at compute_80 and includes compute_89.
This is the minimal direct CMake invocation used for KangEngine:
export PHYSX_ROOT=$HOME/Physics/PhysX/physx
export PHYSX_BUILD=$PHYSX_ROOT/compiler/linux-clang-release-5.8
cmake -S $PHYSX_ROOT/compiler/public \
-B $PHYSX_BUILD \
-DPHYSX_ROOT_DIR=$PHYSX_ROOT \
-DTARGET_BUILD_PLATFORM=linux \
-DCMAKE_BUILD_TYPE=release \
-DPX_OUTPUT_LIB_DIR=$PHYSX_ROOT \
-DPX_OUTPUT_BIN_DIR=$PHYSX_ROOT \
-DPX_GENERATE_STATIC_LIBRARIES=ON \
-DPX_GENERATE_GPU_PROJECTS=ON \
-DPX_GENERATE_GPU_REDUCED_ARCHITECTURES=ON
PHYSX_BUILD can point to any clean build directory. Keep the remaining options
explicit: PhysX’s public CMake entry point requires the root/output paths, while
KangEngine needs static PhysX libraries, GPU projects, and the reduced CUDA
architecture list for CUDA 13.
After configure, confirm compute_70 is gone:
rg 'ARCH_CODE_LIST' \
$PHYSX_BUILD/CMakeCache.txt
Expected ARCH_CODE_LIST includes:
compute_80, compute_86, compute_89, compute_90, compute_100, compute_120
CUDA 13 cuCtxCreate patch¶
PhysX 5.8.0 calls the older 3-argument CUDA Driver API form:
cuCtxCreate(&mCtx, (unsigned int)flags, mDevHandle);
With CUDA 13 headers, cuCtxCreate maps to cuCtxCreate_v4, which expects a
CUctxCreateParams* argument. Patch
$PHYSX_ROOT/source/cudamanager/src/CudaContextManager.cpp
near the CUDA context creation call:
#if CUDA_VERSION >= 13000
CUctxCreateParams ctxCreateParams = {};
status = cuCtxCreate(&mCtx, &ctxCreateParams, (unsigned int)flags, mDevHandle);
#else
status = cuCtxCreate(&mCtx, (unsigned int)flags, mDevHandle);
#endif
Then build:
cmake --build \
$PHYSX_BUILD \
--parallel
The build should finish with:
[100%] Built target PhysXVehicle2
Verify native Ada GPU kernels¶
Check that the rebuilt GPU library contains sm_89 cubins:
/usr/local/cuda/bin/cuobjdump --list-elf \
$PHYSX_ROOT/bin/linux.x86_64/release/libPhysXGpu_64.so \
| rg 'sm_89'
You should see entries such as:
broadphase.sm_89.cubin
MemCopyBalanced.sm_89.cubin
solver.sm_89.cubin
solverTGS.sm_89.cubin
integrationTGS.sm_89.cubin
Use this PhysX binary directory when linking KangEngine against the 5.8.0 checkout:
$PHYSX_ROOT/bin/linux.x86_64/release
Do not run PhysX configure/build commands with sudo. If an earlier build
created root-owned files, repair their ownership:
sudo chown -R "$USER:$USER" ~/Physics/PhysX/physx
Build KangEngine for the selected PhysX configuration.
CPU KangEngine build
CC=clang CXX=clang++ cmake --preset=vcpkg
cmake --build build/release
GPU KangEngine build
KangEngine links PhysXGpu_64; its shared library must be discoverable at
runtime.
make build_all
make build_cuda
make build_python_cuda
Run make validate_physx_gpu for the process-isolated Python GPU regression
suite or make validate_physx_gpu_cpp for the native smoke test. See
PHYSX_GPU.md for the runtime contract.
Run KangEngine.
make run2
macOS¶
Tested with Apple Silicon.
Clone o3de PhysX under
$HOME/Physics/PhysX.mkdir -p ~/Physics cd ~/Physics git clone -b 104.1 https://github.com/o3de/PhysX.git
Install build tools.
brew install coreutils ninja autoconf automake autoconf-archive
Build PhysX.
cd ~/Physics/PhysX/physx ./buildtools/packman/packman update -y ./generate_projects.sh # The O3DE PhysX build system uses the 'mac.x86_64' directory name for all macOS builds, including Apple Silicon. cd compiler/mac.x86_64 cmake --build . --config release
Configure KangEngine.
cmake --preset=vcpkg
Build KangEngine.
cmake --build build/release
Build Targets¶
Common make targets:
make build
make build_debug
make build_python
make build_all
make build_cuda
make build_python_cuda
make build_usd
make build_usd_python
make wheel
make wheel_cuda
make validate_wheel
make validate_wheel_cuda
make validate_physx_gpu
make validate_physx_gpu_cpp
make run2
The executable target is selected in CMakeLists.txt by changing the active MAIN_FILE entry near the example list.
OpenUSD Optional¶
OpenUSD is only needed when configuring KangEngine with -DUSE_USD=ON.
Clone OpenUSD.
cd ~ git clone https://github.com/PixarAnimationStudios/OpenUSD.git
Build OpenUSD into
~/usd_build.mkdir -p ~/usd_build python3 ~/OpenUSD/build_scripts/build_usd.py ~/usd_build
If you build OpenUSD somewhere else, pass
-DUSD_DIR=/path/to/usd_buildto your CMake configure command.USD_DIRis the OpenUSD installation prefix containinginclude/andlib/.
Python Bindings Optional¶
KangEngine exposes a Python module, kangengine, via pybind11. The extension is
built by CMake and must match the consumer’s CPython ABI, Python minor version,
platform, and architecture.
Create a virtual environment with Python 3.12 using
uv.uv venv python/.venv --python 3.12 source python/.venv/bin/activate
Build the extension from the repo root.
make build_pythonOr with USD support:
make build_usd_pythonInstall the Python package in editable mode.
uv pip install -e ./python
Run an example.
python ./python/examples/view_bvh_character.py
Python Wheels¶
KangEngine builds separate native wheels on each target platform. Wheel builds
use python/.venv/bin/python by default, so activating the development virtual
environment is optional. Create and populate that environment as described in
the previous section before building a wheel.
The distributed wheels intentionally disable OpenUSD. This keeps the native
extension independent of OpenUSD, TBB, and USD plugin resources. USD-enabled
development builds remain available through make build_usd_python, but a
USD-enabled distribution wheel is not currently produced.
Build and preserve a wheel under python/dist:
# macOS, CPU PhysX
make wheel
# Linux, CUDA and the configured GPU PhysX build
make wheel_cuda
The filename records the active CPython ABI and platform, for example:
python/dist/kangengine-0.1.0-cp312-cp312-macosx_26_0_arm64.whl
Wheel creation uses a temporary staging directory, so stale files under a
previous setuptools build directory cannot enter the package. The
kangengine/assets/external directory is excluded; the remaining runtime
assets, Python modules, type information, and _kangengine.so are included.
To build, install, and test a temporary wheel without changing the development environment, run:
make validate_wheel
make validate_wheel_cuda # Linux CUDA host only
Validation checks the native platform tag, no-USD build policy, package contents, public API, and type-stub surface. It installs KangEngine into a temporary target directory, reuses the development environment’s Python dependencies, and removes the temporary wheel and installation afterward.
To test the preserved wheel as a consumer, create a separate environment with the matching Python version and install the wheel there:
python3.12 -m venv /tmp/kangengine-wheel-venv
source /tmp/kangengine-wheel-venv/bin/activate
python -m pip install --upgrade pip
python -m pip install python/dist/kangengine-0.1.0-cp312-cp312-macosx_26_0_arm64.whl
python -c "import kangengine as ke; assert not ke.scene.has_usd_support()"
Use the corresponding filename emitted by make wheel_cuda on Linux.
The macOS wheel contains the statically linked PhysX CPU libraries. The Linux CUDA wheel still requires a compatible NVIDIA driver, CUDA runtime policy, and GPU PhysX environment for full simulation validation. Build and test each wheel on the same operating-system and architecture family on which it will be distributed.
Build the Documentation¶
Build the Python extension first so the API reference can import the pybind11 module:
make build_python
make docs
To include APIs that exist only in a USD-enabled build:
make build_usd_python
make docs