Vdeps is a lightweight Python script that compiles cmake dependencies for you. This is great if you just went to compile them in a separate directory without dealing with the fun task of trying to link the cmakes builds together directly. In the end you just want to build some libraries and copy them into a folder for your project to link, right?
NOTE: Vdeps is vibe coded, without too much code oversight. Intended as a throwaway tool of sorts. Use at your own risk.
vdeps.py builds dependency libraries and tools defined in vdeps.toml, copying artefacts to lib/ and tools/ directories organised by platform and build configuration.
# Build all dependencies
python vdeps.py
# Build specific dependencies by name (case-insensitive)
python vdeps.py nvrhi assimp
# Skip project regeneration if build exists (--build flag)
python vdeps.py --build
python vdeps.py nvrhi --build
# Skip rebuilding when copied outputs still exist and dependency HEAD is unchanged
python vdeps.py --auto-skip
# Combine with --build for fast incremental runs
python vdeps.py --build --auto-skip
# Cap parallel build workers on RAM-constrained boxes (default = all cores)
python vdeps.py --parallel 4
# Build with ThreadSanitizer / AddressSanitizer / MemorySanitizer / UBSan
python vdeps.py --sanitize thread
python vdeps.py --sanitize address
python vdeps.py --sanitize memory
python vdeps.py --sanitize thread,undefined
# Cross-compile to a specific architecture on macOS (arm64 or x64; aliases: aarch64, x86_64, amd64)
# Threads CMAKE_OSX_ARCHITECTURES through cmake and suffixes lib/ and build/ paths so arm64 and x64
# outputs do not collide. Default (omitted) leaves the host arch's existing paths unchanged.
python vdeps.py --arch arm64
python vdeps.py --arch x64 # x86_64 build for Intel Macs (or testing under Rosetta on arm64)
python vdeps.py --arch x64 --sanitize thread
# Generate a thin CMake wrapper at vdeps/CMakeLists.txt
python vdeps.py --generate-cmakeTip: add .vdeps-state.json to your project's .gitignore to avoid committing local auto-skip state.
Dependency selection: Build specific dependencies by name. Names are case-insensitive and must match entries in vdeps.toml. Invalid characters are rejected.
--generate-cmake reads vdeps.toml, writes vdeps/CMakeLists.txt, and exits without building anything. It is incompatible with --build, --clean, --auto-skip, positional dependency names, and --llvm. LLVM and runtime options are controlled via CMake cache variables in the generated wrapper, not CLI flags.
--auto-skip only skips for clean git repos under vdeps/; dirty repos or non-git directories fall back to normal builds.
python vdeps.py --generate-cmake creates vdeps/CMakeLists.txt for parent projects to consume with add_subdirectory(vdeps). Generated targets always run vdeps.py --build --auto-skip <dep> so parent CMake builds are fast by default; if you need a forced rebuild or unusual troubleshooting, run vdeps.py directly.
add_subdirectory(vdeps)
add_dependencies(my_app vdeps_nvrhi)You can also depend on the aggregate target if you want all configured dependencies built:
add_subdirectory(vdeps)
add_dependencies(my_app vdeps_all)The generated wrapper exposes cache toggles for MSVC runtime and compiler options:
| Option | Default | Description |
|---|---|---|
VDEPS_USE_LLVM |
OFF | Use Clang/LLVM compiler |
VDEPS_STATIC_RUNTIME |
ON* | Build with /MT (static runtime) |
VDEPS_DYNAMIC_RUNTIME |
OFF | Build with /MD (dynamic runtime) |
VDEPS_SANITIZE |
"" |
Sanitizer set forwarded to vdeps.py --sanitize (e.g. thread, address). Empty disables. Generates vdeps_all_tsan. |
VDEPS_PARALLEL |
"" |
Cap parallel build workers (forwarded as --parallel N). Empty uses all cores. |
VDEPS_ARCH |
"" |
Target architecture on macOS (forwarded as --arch arm64 / --arch x64). Empty uses host arch. |
*When neither VDEPS_STATIC_RUNTIME nor VDEPS_DYNAMIC_RUNTIME is set, VDEPS_STATIC_RUNTIME defaults to ON.
Enable sanitizers via the wrapper:
set(VDEPS_SANITIZE "thread" CACHE STRING "" FORCE)
add_subdirectory(vdeps)
add_dependencies(my_app vdeps_all_tsan)Sanitized outputs land under lib/ and tools/ directories tagged with the sanitizer set (e.g. linux_thread_debug/). vdeps.py exports TSAN_OPTIONS (halt_on_error=0, ignore_noninstrumented_modules=1) into the dep build environment; the consuming project's root CMakeLists is responsible for setting TSAN_OPTIONS (and equivalents for ASan/MSan/UBSan) for the final app build/run.
Build both runtimes for combined packages:
set(VDEPS_STATIC_RUNTIME ON CACHE BOOL "" FORCE)
set(VDEPS_DYNAMIC_RUNTIME ON CACHE BOOL "" FORCE)
add_subdirectory(vdeps)Build with LLVM and dynamic runtime:
set(VDEPS_USE_LLVM ON CACHE BOOL "" FORCE)
set(VDEPS_DYNAMIC_RUNTIME ON CACHE BOOL "" FORCE)
add_subdirectory(vdeps)| Target | Description |
|---|---|
vdeps_all |
Top-level aggregate (depends on enabled variants) |
vdeps_all_mt |
All deps with static runtime (/MT) |
vdeps_all_md |
All deps with dynamic runtime (/MD) |
vdeps_all_llvm_mt |
All deps with LLVM + static runtime |
vdeps_all_llvm_md |
All deps with LLVM + dynamic runtime |
vdeps_all_tsan |
All deps with sanitizers (only when VDEPS_SANITIZE is set) |
vdeps_<name>_mt |
Individual dep with static runtime |
vdeps_<name>_md |
Individual dep with dynamic runtime |
vdeps_<name>_<runtime>_tsan |
Individual dep with sanitizers |
Arch is a --parallel-class axis (modifier) rather than a --sanitize-class axis (multiplier): VDEPS_ARCH is forwarded to every vdeps_build_dep invocation as --arch $VDEPS_ARCH, but the target matrix is not duplicated. Consumers that want both arm64 and x64 builds use two separate build directories.
This wrapper is build orchestration only in v1. It does not create imported CMake targets, propagate include directories, or add link instructions automatically, so linking remains manual.
Dependencies are configured in vdeps.toml:
# Optional: centralise build artefacts
temp_dir = "builds"
[[dependency]]
name = "nvrhi"
rel_path = "nvrhi"
cxx_standard = 20
libs = ["nvrhi_vk", "rtxmu", "nvrhi"]
executables = []
cmake_options = [
"-DNVRHI_INSTALL=OFF",
"win:-DNVRHI_WITH_DX11=OFF",
"linux,mac:-DNVRHI_WITH_VULKAN=ON",
"!win:-DNOT_WINDOWS=ON",
]| Field | Description |
|---|---|
name |
Display name for logging and selective building |
rel_path |
Relative path to dependency in vdeps/ directory |
libs |
Library base names to copy (e.g. ["nvrhi"] matches libnvrhi.a or nvrhi.lib) |
executables |
Executable base names to copy to tools directory |
extra_files |
Specific filenames to copy (e.g. ["slangc.exe", "slang.dll"]) |
cmake_options |
List of CMake flags passed during configuration |
cxx_standard |
C++ standard version (default: 20) |
extra_link_dirs |
Additional linker search paths for this dependency |
build |
If false, skips CMake configure and build steps (default: true) |
install |
List of custom copy rules (see below) |
Variable Substitution: Use ${ROOT_DIR} in cmake_options to reference the absolute path of the directory containing vdeps.py.
Install Rules: Use install to copy files matching a glob pattern to a target directory (lib or tools).
install = [
{ pattern = "bin/*.dll", target = "tools" },
{ pattern = "data/**/*", target = "tools/data" }
]Platform-specific syntax: Use win:, linux:, mac: prefixes for platform-specific items in arrays. Negation with ! and multiple platforms with commas: "win,linux:-DFEATURE=ON", "!win:-DNOT_WIN=ON".
Centralised builds: Add temp_dir = "builds" at top-level to redirect build directories from {dependency}/build_{config} to {temp_dir}/{name}_{config}.
root/
├── vdeps.py
├── vdeps.toml
├── lib/
│ ├── linux_debug/
│ ├── linux_release/
│ ├── mac_debug/ # arm64 host default (no --arch)
│ ├── mac_release/
│ ├── mac_arm64_debug/ # explicit --arch arm64
│ ├── mac_arm64_release/
│ ├── mac_x64_debug/ # explicit --arch x64 (cross-compile or x86_64 host)
│ ├── mac_x64_release/
│ ├── win_debug/
│ ├── win_release/
│ ├── win_llvm_debug/
│ ├── win_llvm_release/
│ ├── win_md_debug/
│ ├── win_md_release/
│ ├── win_llvm_md_debug/
│ └── win_llvm_md_release/
└── tools/
├── (mirror of lib/, same layout)
The _md variants use dynamic MSVC runtime libraries (/MD, /MDd). The _llvm_ prefix indicates Clang/LLVM builds. With --sanitize thread, output paths use a _thread tag (e.g. linux_thread_debug/, win_llvm_thread_release/); --sanitize address produces _address, comma-separated sets produce underscore-joined tags like _thread_address. The build directory is tagged the same way (build_thread_debug, build_x64_thread_debug, etc.). --arch x64 adds a _x64 segment on macOS (arch comes before sanitize: mac_x64_thread_debug). --parallel N does not affect directory names -- it only caps the worker count.
macOS cross-compile tip: building with --arch x64 from an arm64 host requires Rosetta 2 for any host tools the deps run during their build (e.g. SPIRV-Tools codegen). Install it once with softwareupdate --install-rosetta.
- Generator: Ninja
- Compiler: Clang/Clang++
- Library extension:
.a - Executable extension: none
- Warning suppression:
-w(can be overridden viacmake_options)
- Generator: Visual Studio (MultiConfig)
- Compiler: MSVC
- Library extension:
.lib - Executable extension:
.exe - Release builds use
RelWithDebInfofor PDB files - Warning suppression:
/W0(can be overridden viacmake_options)
# Run all tests
./venv/bin/python -m pytest tests/ -v
# Or with coverage
./venv/bin/python -m pytest tests/ -v --cov=vdepsThe test suite uses functional CMake projects with a Python artefact generator (tests/fixtures/vdeps/gen_artifact.py). These mock projects build quickly and test platform-specific behaviour, error handling, and configuration options without requiring actual C++ compilation.
To run specific test categories:
# Platform-specific tests only
./venv/bin/python -m pytest tests/test_vdeps_platforms.py -v
# Configuration tests
./venv/bin/python -m pytest tests/test_vdeps_configuration.py -v- Python 3.10+
- CMake 3.15+
- Ninja (Linux/macOS)
- Visual Studio 2019+ (Windows)
Vdeps is released under the MIT license:
Copyright 2026 UAA Software
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute,
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.