Skip to content

Comparison

There are three CMake formatters in active use: cmakefmt, cmake-format, and gersemi. This page summarises the key differences to help you choose.

Featurecmakefmtcmake-formatgersemi
Command specs150+ (CMake 4.3)~100 (CMake 3.20)Built-in
Active maintenanceYesNo (last release 2021)Yes
Recursive discoveryBy defaultNo (explicit file list)By default
Parallel formattingBy defaultNoNo
LanguageRustPythonPython
InstallHomebrew, cargo, pip, conda, binarypippip
LSP serverBuilt-in (cmakefmt lsp)NoNo
VS Code extensionFirst-partyFirst-partyNo
Watch mode--watchNoNo
Check mode--check--check-only--check
Diff output--diffNoNo
Git-aware selection--staged, --changedNoNo
Range formatting--linesNoNo
GitHub Actioncmakefmt/cmakefmt-actionNoNo
CI report formatsGitHub, Checkstyle, JUnit, SARIF, JSONNoNo
Config fileYAML or TOMLPython, YAML, or JSONNone
Config discoveryPer-file, walks up to .git rootDirectory-basedNone
Config autocompleteJSON Schema on SchemaStoreNoNo
Migrate existing configcmakefmt config convert
Parse tree dumpcmakefmt dump ast/parse--dump parseNo
Stdin formatting--stdin-path <path> -via --via stdin
LicenseMIT OR Apache-2.0Apache-2.0MIT

cmakefmt recursively discovers all CMakeLists.txt and *.cmake files by default — just point it at your project root. It also formats them in parallel using all available CPUs. On a 611-file repository this means sub-second formatting of the entire project.

cmake-format requires you to pass every file explicitly (or write a find + xargs wrapper). It has no parallel mode.

gersemi supports recursive discovery but has no parallel mode.

cmakefmt is a native binary with no interpreter startup overhead. On a cold invocation it formats a typical CMakeLists.txt in under 10 ms. Python tools (cmake-format, gersemi) typically spend 200–500 ms just starting the interpreter before any file is touched — noticeable on every save in an editor.

For large repositories cmakefmt also ships a content-addressed cache (--cache) so unchanged files are not re-parsed between runs.

See Performance for full benchmarks.

cmakefmt supports YAML and TOML config files (.cmakefmt.yaml, .cmakefmt.toml) with a structured, documented schema. Config is discovered automatically by walking up from the file being formatted to the filesystem root, mirroring how tools like rustfmt and ruff work.

cmakefmt also publishes a JSON Schema to SchemaStore, which means editors with YAML language support (VS Code with the Red Hat YAML extension, JetBrains IDEs, Neovim with yaml-language-server) automatically provide autocomplete, validation, and inline documentation for .cmakefmt.yaml — no per-user setup required.

cmake-format supports a wider variety of config formats (Python files, YAML, JSON) but has no schema and no autocomplete support. gersemi has no config file at all — its formatting is entirely opinionated.

cmakefmt ships a first-party VS Code extension (cmakefmt.vscode-cmakefmt) with format-on-save support. It works in Neovim via conform.nvim, Helix, Zed, and Emacs via apheleia — see the Editor Integration page.

cmake-format has a widely-used VS Code extension with over 500k installs. gersemi has no editor integration.

cmakefmt ships a first-party GitHub Action (cmakefmt/cmakefmt-action) that installs the right binary for the runner OS in one uses: line — see the CI Integration page. It also outputs GitHub Actions annotations via --report-format github, Checkstyle XML, JUnit XML, and SARIF JSON for downstream tooling.

Neither cmake-format nor gersemi ship a GitHub Action.

cmake-format last released in 2021 and is in maintenance-only mode. The Python 3 ecosystem has moved on and there are known compatibility issues with newer Python versions. gersemi is actively maintained. cmakefmt is under active development with frequent releases.

cmakefmt can convert your existing cmake-format config automatically:

Terminal window
cmakefmt config convert .cmake-format.yaml > .cmakefmt.yaml

See the Migration Guide for a full walkthrough.

Docs track main. For historical docs, check out a release tag in the repository and build docs/ locally.