cmakex is a lightweight, GitHub-first helper for CMake FetchContent dependencies.
It does not introduce a package manifest or a custom CMake DSL. The project source of truth remains normal CMake files:
- dependencies are written to
cmake/dependencies.cmake - the root
CMakeLists.txtincludes that file - users still link targets with
target_link_libraries(...)
cmakex is the command name. It is not the system cmake command:
cmakex search fmtInstall as an isolated CLI with pipx:
pipx install "git+https://github.com/trdthg/cmakex.git"
cmakex --helpInstall as an isolated CLI with uv:
uv tool install "git+https://github.com/trdthg/cmakex.git"
cmakex --helpRun without permanently installing with uvx:
uvx --from "git+https://github.com/trdthg/cmakex.git" cmakex --helpuvx is the short alias for uv tool run.
Create a minimal project:
cmakex new hello
cd helloExample output:
Created CMake project: hello
path: /path/to/hello
Search for a dependency:
cmakex search fmtExample output:
repo stars updated description
-------------------------------- ----- ---------- ----------------------------------------
fmtlib/fmt 23499 2026-05-20 A modern formatting library
MengRao/fmtlog 1015 2026-05-14 fmtlog is a performant fmtlib-style...
WGUNDERWOOD/tex-fmt 806 2026-05-20 An extremely fast LaTeX formatter...
Use `cmakex latest owner/repo` to inspect the latest tag before installing.
Search results are GitHub repositories; FetchContent/CMake compatibility is not guaranteed.
Inspect release/tag candidates:
cmakex latest fmtlib/fmtExample output:
fmtlib/fmt
refs:
latest: 12.1.0 (GitHub latest release)
#2: 12.0.0 (semver tag)
#3: 11.2.0 (semver tag)
#4: 11.1.4 (semver tag)
#5: 11.1.3 (semver tag)
Install fmt at a specific tag:
cmakex install fmtlib/fmt==12.1.0install writes cmake/dependencies.cmake, runs a CMake probe by default, downloads the dependency into build/_deps, and prints a link template.
Example output:
Installed fmt
repository: https://github.com/fmtlib/fmt.git
ref: 12.1.0
source: explicit tag shorthand
Detected CMake targets:
fmt
Next step: add this to your CMakeLists.txt and replace placeholders as needed:
target_link_libraries(hello PRIVATE fmt)
Copy-paste on Linux/macOS:
printf '\ntarget_link_libraries(hello PRIVATE fmt)\n' >> CMakeLists.txt
Add the link line:
target_link_libraries(hello PRIVATE fmt)Or copy-paste the generated shell command on Linux/macOS:
printf '\ntarget_link_libraries(hello PRIVATE fmt)\n' >> CMakeLists.txtBuild and run:
cmakex runExample output:
-- {fmt} version: 12.1.0
-- Build files have been written to: /path/to/hello/build
[100%] Built target hello
Hello from cmakex
cmakex new hello creates:
hello/
├── CMakeLists.txt
├── cmake/
│ └── dependencies.cmake
└── src/
└── main.c
The generated CMakeLists.txt enables both C and CXX:
cmake_minimum_required(VERSION 3.24)
project(hello C CXX)
include(cmake/dependencies.cmake)
add_executable(hello src/main.c)CXX is enabled because many useful FetchContent dependencies expose C++ targets even when your app starts as C.
cmakex new <name>
cmakex search <query>
cmakex latest <name-or-owner/repo>
cmakex install <owner/repo|github-url|git-url>[==tag]
cmakex uninstall <name>
cmakex list
cmakex probe <name>
cmakex build [target]
cmakex run [target] [-- args]Searches GitHub repositories:
cmakex search fmtSearch results are GitHub repositories, not curated packages. cmakex does not guarantee that every result supports direct FetchContent_MakeAvailable(...).
GitHub API calls are cached under ~/.cache/cmakex. Set GITHUB_TOKEN if you hit rate limits:
export GITHUB_TOKEN=...Shows latest release/tag candidates:
cmakex latest fmtlib/fmtExample output:
fmtlib/fmt
refs:
latest: 12.1.0 (GitHub latest release)
#2: 12.0.0 (semver tag)
#3: 11.2.0 (semver tag)
Install from GitHub:
cmakex install fmtlib/fmt==12.1.0Equivalent explicit form:
cmakex install fmtlib/fmt --tag 12.1.0Other refs:
cmakex install owner/repo --branch main
cmakex install owner/repo --commit abc1234Override the local dependency name:
cmakex install sqlite/sqlite --name sqlite3 --tag version-3.46.0Skip the automatic CMake probe:
cmakex install fmtlib/fmt==12.1.0 --no-probePass upstream CMake cache options:
cmakex install opencv/opencv==4.10.0 --set WITH_IPP=OFF--set KEY=VALUE can be repeated.
Shows local dependencies without network access:
cmakex listRemoves the matching FetchContent_Declare(...) block and its FetchContent_MakeAvailable(...) call:
cmakex uninstall fmtRuns CMake configure and tries to detect targets via the CMake File API:
cmakex probe fmtDefault build directory is build. Dependencies normally land in:
build/_deps/
Use another build directory:
cmakex probe fmt --build-dir cmake-build-debugConfigures and builds:
cmakex build
cmakex build helloBuilds and runs an executable target:
cmakex run
cmakex run hello
cmakex run hello -- arg1 arg2If no target is passed, cmakex uses the name from project(...).
This section is intentionally small and can grow as more repositories are tested.
CLI11 is a C++ command-line parser. It works well with direct FetchContent embedding.
cmakex install CLIUtils/CLI11==v2.6.2Expected target:
target_link_libraries(<your-app> PRIVATE CLI11)raylib is a C game programming library. It can be installed from GitHub:
cmakex install raysan5/raylib==6.0OpenCV is a large CMake project. It may not behave like a small library when embedded directly with FetchContent_MakeAvailable(opencv).
Basic install:
cmakex install opencv/opencv==4.10.0If OpenCV fails around IPP internals, for example:
hal/ipp/src/mean_ipp.cpp
fatal error: opencv2/core/base.hpp: No such file or directory
the header may exist, but the OpenCV internal ipphal target did not receive the expected include path in this embedded build. A practical workaround is to disable IPP:
rm -rf build
cmakex uninstall opencv
cmakex install opencv/opencv==4.10.0 --set WITH_IPP=OFFFor faster and smaller builds, restrict modules:
rm -rf build
cmakex uninstall opencv
cmakex install opencv/opencv==4.10.0 \
--set WITH_IPP=OFF \
--set BUILD_LIST=core,imgproc,imgcodecs \
--set BUILD_TESTS=OFF \
--set BUILD_PERF_TESTS=OFF \
--set BUILD_EXAMPLES=OFFCommon module targets:
target_link_libraries(<your-app> PRIVATE opencv_core opencv_imgproc opencv_imgcodecs)For:
cmakex install fmtlib/fmt==12.1.0cmakex writes:
include(FetchContent)
FetchContent_Declare(
fmt
GIT_REPOSITORY https://github.com/fmtlib/fmt.git
GIT_TAG 12.1.0
)
FetchContent_MakeAvailable(fmt)With options:
cmakex install opencv/opencv==4.10.0 --set WITH_IPP=OFF --no-probecmakex writes:
# cmakex: option WITH_IPP=OFF
FetchContent_Declare(
opencv
GIT_REPOSITORY https://github.com/opencv/opencv.git
GIT_TAG 4.10.0
)
set(WITH_IPP OFF CACHE BOOL "cmakex option for opencv" FORCE)
FetchContent_MakeAvailable(opencv)cmakex is not a full package manager.
It currently does not:
- maintain a package registry
- guarantee GitHub search results are installable
- automatically edit your business
target_link_libraries(...) - patch upstream projects
- manage binary packages
The intended workflow is:
- find a GitHub repo
- write a standard
FetchContent_Declare(...) - probe for target candidates
- let the user link the right target in normal CMake
Run the local test suite:
PYTHONPATH=src python3 -m unittest discover -s tests -v
python3 -m compileall -q src tests