The missing tools in CMake:
cmk new: Create a new CMake boilerplate project.cmk run: Builds and runs a specified executable target, getting rid of the build directory and binary path.cmk build: Automatically discovers the project's build directory and invokes the build process from any subdirectory.cmk build-tu: Speeds up iteration by compiling a single source file (translation unit) on its own.cmk fmt: Formats C/C++ source files withclang-format. Pass a positional source path to format a single file (cmk fmt src/foo.cpp); otherwise selects via--all(all tracked files),--staged, or--unstaged. Files matching[fmt] ignoreglob patterns in.cmk.tomlare skipped.cmk init: Scaffold a.cmk.tomlin the project root with commented-out examples for[build],[vars],[env],[fmt],[lint]. Pass-f/--forceto overwrite.cmk completions <shell>: Print shell completions to stdout. Supportsbash,zsh,fish,powershell,elvish. Example:cmk completions zsh > ~/.zfunc/_cmk.cmk lint: Lints C/C++ source files withclang-tidyagainst the build directory'scompile_commands.json. Same--all/--staged/--unstagedselection asfmt, plus--fix(serial),-W/--warnings-as-errors, and-b/--buildto pick the build dir. To target a single TU, pass a positional source path (cmk lint src/foo.cpp) or-i/--interactiveto pick fromcompile_commands.jsonvia fzf. Results are cached per-file under<build>/.cmk-lint-cache/; unchanged files (same source mtime/size, cdb mtime,.clang-tidychain, and CLI args) replay the cached output without re-invoking clang-tidy. Pass--no-cacheto bypass. Honours[lint]in.cmk.toml(ignore,warnings_as_errors,header_filter,extra_args).
Package management (CPM):
cmk add owner/repo: Track a GitHub release in the global package index (~/.config/cmk/pkg.json). Pass-p/--projectto also insertCPMAddPackage("gh:owner/repo#vTAG")into the rootCMakeLists.txt(skipped if the package is already present).cmk get name: Print the cached release for a tracked package (alias or fullowner/repo).cmk update: Refresh the latest release tags for all tracked packages and the bundled CPM bootstrap script. Pass-p/--projectto also scan the rootCMakeLists.txtforCPMAddPackage("gh|gl|bb:owner/repo#tag")URIs, query GitHub for each, print a diff, and (with confirmation, or-yto skip) splice in the new versions while preserving comments and formatting.cmk pkg option <name> KEY=VALUE...: Rewrite a URI-formCPMAddPackage("gh:owner/repo#tag")into the equivalent keyword form (NAME+GITHUB_REPOSITORY+GIT_TAG) withOPTIONS "KEY VALUE"appended.<name>matches a repo basename (fmt), fullowner/repo, or a global-index alias. Example:cmk pkg option fmt FMT_INSTALL=ON.
Requirement:
- Only works with CMake projects with
Ninjaas the generator(Ninja Multi-Configis not supported). fzfis required for interactive selection.- The project root discovery only works in a git repository.
Environment Variables:
CMK_DEFAULT_JOBS: The default number of build jobs to use. If not set, it defaults to the number of available CPU cores minus one.
Example of .cmk.toml:
[vars]
DEPS_DIR = "${PROJECT_ROOT}/.deps"
DEPS_INSTALL = "${DEPS_DIR}/install"
[env]
PATH = { prepend = ["${DEPS_INSTALL}/bin"] }
CPATH = { prepend = ["${DEPS_INSTALL}/include"] }
PKG_CONFIG_PATH = { prepend = ["${DEPS_INSTALL}/lib/pkgconfig"] }
LIBRARY_PATH = { prepend = ["${DEPS_INSTALL}/lib"] }
[env.macos]
DYLD_LIBRARY_PATH = { prepend = ["${DEPS_INSTALL}/lib"] }
[env.linux]
LD_LIBRARY_PATH = { prepend = ["${DEPS_INSTALL}/lib", "${DEPS_INSTALL}/lib64"] }
PKG_CONFIG_PATH = { prepend = ["${DEPS_INSTALL}/lib64/pkgconfig"] }
LIBRARY_PATH = { prepend = ["${DEPS_INSTALL}/lib64"] }
[build]
default = "build/debug" # used when PWD isn't inside a build dir and there are multiple
[fmt]
ignore = ["third_party/**", "*.pb.h"]
[lint]
ignore = ["third_party/**", "*.pb.h"]
warnings_as_errors = false
header_filter = "^(src|include)/"
extra_args = ["-quiet"]