Skip to main content

A fast, correct CMake formatter

Project description

cmakefmt banner

cmakefmt

CI
CI Pages Coverage CodSpeed

Package
Crates.io dependency status

Security & Quality
REUSE status OpenSSF Scorecard OpenSSF Best Practices

A lightning-fast, workflow-first CMake formatter — built in Rust, built to last.

cmakefmt demo

The above demo was generated with VHS.

cmakefmt replaces the aging Python cmake-format tool with a single native binary. Same spirit. No Python.

  • crates.io: cmakefmt-rust
  • CLI name: cmakefmt

[!NOTE]

This project is independent from other Rust implementations, including: azais-corentin/cmakefmt and yamadapc/cmakefmt.

Contents

Why cmakefmt?

  • 25× faster — not a typo. Geometric-mean speedup of 25.33x over cmake-format on real-world corpora. Pre-commit hooks that once made you wince now finish before you blink.
  • Zero dependencies. One binary. No Python environment, no virtualenv bootstrap, no dependency drift. Drop it in CI and forget about it.
  • Built for actual workflows. --check, --diff, --staged, --changed, --files-from, --show-config, --explain-config, semantic verification, JSON reporting — all first-class, not scripted workarounds.
  • Knows your commands. Teach cmakefmt the argument structure of your project's custom CMake functions and macros. No more generic token-wrapping for code you wrote.
  • Errors that actually help. Parse and config failures come with file/line context, source snippets, and reproduction hints — not opaque parser noise.
  • Designed for real repositories. Comment preservation, disable-region passthrough, config discovery, ignore files, Git-aware file selection, and opt-in parallelism are core features, not afterthoughts.

Performance

Fixture Lines cmakefmt ms cmake-format ms Speedup
abseil/CMakeLists.txt 280 5.358 172.882 32.27×
catch2/CMakeLists.txt 230 5.177 110.495 21.34×
cli11/CMakeLists.txt 283 5.174 125.992 24.35×
cmake_cmbzip2/CMakeLists.txt 25 4.563 63.034 13.81×
googletest/CMakeLists.txt 36 4.376 65.244 14.91×
ggml/CMakeLists.txt 498 7.371 216.193 29.33×
llama_cpp/CMakeLists.txt 286 5.755 131.230 22.80×
llvm_tablegen/CMakeLists.txt 83 4.439 79.608 17.93×
mariadb_server/CMakeLists.txt 656 9.097 489.035 53.76×
nlohmann_json/CMakeLists.txt 237 5.035 140.580 27.92×
opencv_flann/CMakeLists.txt 2 4.263 54.812 12.86×
protobuf/CMakeLists.txt 351 5.478 114.711 20.94×
spdlog/CMakeLists.txt 413 6.461 220.804 34.17×
qtbase_network/CMakeLists.txt 420 7.852 293.745 37.41×
xnnpack/CMakeLists.txt 1354 26.965 1432.939 53.14×

Geometric-mean speedup across the full corpus: 25.33×. On a 220-file batch, --parallel 8 improves throughput by 3.80× vs serial.

Full methodology and profiler notes: cmakefmt.dev/performance/.

Update the pinned local corpus and generate local before/after review artifacts with:

python3 scripts/fetch-real-world-corpus.py
scripts/review-real-world-corpus.sh

Installation

Homebrew (macOS):

brew install cmakefmt/cmakefmt/cmakefmt

Cargo (any platform):

cargo install cmakefmt-rust

pip (any platform with Python):

pip install cmakefmt

conda-forge:

conda install -c conda-forge cmakefmt

Pre-built binaries (Linux, macOS, and Windows):

Download the .zip / .tar.gz for your platform from GitHub Releases, extract, and place the binary on your PATH.

Build from source:

git clone https://github.com/cmakefmt/cmakefmt
cd cmakefmt
cargo install --path .

Verify:

cmakefmt --version

Release channels and support levels are documented at cmakefmt.dev/release/. Shell completion installation instructions are available at cmakefmt.dev/install/.

Quick Start

1. Generate a starter config in your project root:

cmakefmt --dump-config > .cmakefmt.yaml

2. Dry-run — check your whole project without touching any files:

cmakefmt --check .

3. Apply formatting:

cmakefmt --in-place .

4. Format only the files you're about to commit:

cmakefmt --staged --check

Common Workflows

Task Command
Format file to stdout cmakefmt CMakeLists.txt
Rewrite files in place cmakefmt --in-place .
CI check cmakefmt --check .
Preview which files would change cmakefmt --list-changed-files .
See the exact patch cmakefmt --diff CMakeLists.txt
Verify semantics while formatting to stdout cmakefmt --verify CMakeLists.txt
Pre-commit guard (staged files only) cmakefmt --staged --check
PR-scoped check cmakefmt --changed --since origin/main --check
Machine-readable CI output cmakefmt --check --report-format json .
GitHub Actions annotations cmakefmt --check --report-format github .
Checkstyle / JUnit / SARIF output cmakefmt --check --report-format checkstyle .
Pin the required binary version in CI cmakefmt --required-version 1.0.0 --check .
Speed up repeated large-repo checks cmakefmt --cache --check .
Roll out formatting file-by-file cmakefmt --require-pragma --check .
Find project-specific commands cmakefmt --list-unknown-commands .
Watch and auto-format on save cmakefmt --watch .
Explain formatting decisions cmakefmt --explain CMakeLists.txt
Read from stdin cat CMakeLists.txt | cmakefmt -

Configuration

cmakefmt searches upward from each file for .cmakefmt.yaml, .cmakefmt.yml, or .cmakefmt.toml. YAML is recommended for larger configs.

Example .cmakefmt.yaml:

format:
  line_width: 100
  tab_size: 4

style:
  command_case: lower
  keyword_case: upper

markup:
  enable_markup: true

Debug which config a file is actually using:

cmakefmt --show-config-path src/CMakeLists.txt
cmakefmt --show-config src/CMakeLists.txt
cmakefmt --explain-config

Migrate from an existing cmake-format config:

cmakefmt --convert-legacy-config .cmake-format.py > .cmakefmt.yaml

Full config reference: cmakefmt.dev/config/.

Formatter Disable Regions

Selectively opt out of formatting with barrier comments.

There are three barrier styles:

  1. Legacy cmake-format directives:

    # cmake-format: off
    set(MESSY_THING  a   b   c)   # kept verbatim
    # cmake-format: on
    
  2. Native directive barriers, using either cmakefmt or the shorter fmt spelling:

    # cmakefmt: off
    set(MESSY_THING  a   b   c)   # kept verbatim
    # cmakefmt: on
    
    # fmt: off
    set(MESSY_THING  a   b   c)   # kept verbatim
    # fmt: on
    
  3. Fence barriers, which toggle formatting on and off each time # ~~~ appears:

    # ~~~
    set(MESSY_THING  a   b   c)   # kept verbatim
    # ~~~
    

Use directive barriers when you want an explicit start/end marker, and fence barriers when you want a shorter toggle-style block.

Library Usage

cmakefmt is also available as a Rust library:

use cmakefmt::{format_source, Config};

fn main() -> Result<(), cmakefmt::Error> {
    let src = r#"target_link_libraries(foo PUBLIC bar baz)"#;
    let out = format_source(src, &Config::default())?;
    println!("{out}");
    Ok(())
}

Full API docs: cmakefmt.dev/api/.

Documentation

Start here: https://cmakefmt.dev.

Doc Description
Install Install options, first-project setup, CI wiring
Coverage How coverage is measured, published, and interpreted
Release Channels Release contract, support levels, and release artifacts
CLI Reference Every flag, exit code, and discovery rule
Config Reference Full config schema with examples
Formatter Behavior How the formatter makes layout decisions
Migration from cmake-format Incremental rollout guide and CLI mapping
Library API Embedding cmakefmt in your own Rust tools
Troubleshooting Common issues and debug workflow
Performance Benchmark methodology and profiler notes
Contributing How to contribute, run tests, and open PRs
Changelog What's changed in each release

Preview the full docs locally:

cd docs && npm install && npm run dev

Project Layout

cmakefmt/
├── docs/        # Astro + Starlight source published to cmakefmt.dev
├── src/         # CLI, library API, parser, config, spec, formatter
├── tests/       # integration tests, snapshots, and fixtures
├── benches/     # Criterion benchmarks
├── scripts/     # repo maintenance and docs helpers
└── .github/     # CI and Pages workflows

Key modules under src/:

  • main.rs: CLI entry point and workflow orchestration
  • lib.rs: public library API
  • config/: config loading, merging, and legacy conversion
  • parser/: pest grammar, AST, and parse pipeline
  • spec/: built-in and user-defined command registry
  • formatter/: AST-to-doc formatting logic and comment handling
  • files.rs: file discovery and ignore handling

Development

cargo fmt --check                          # formatting
cargo clippy --all-targets -- -D warnings  # lints
cargo test                                 # all tests
cargo llvm-cov --workspace --all-targets   # coverage
cargo bench                                # benchmarks

Install pre-commit hooks:

pre-commit install
pre-commit install --hook-type pre-push

Status

The repository is stable and actively maintained. cmakefmt is still pre-1.0, so release packaging, package-manager distribution, and some output or API details may continue to evolve. The built-in command registry is audited through CMake 4.3.1.

Hit something unexpected? See Troubleshooting or run:

cmakefmt --debug --check path/to/CMakeLists.txt

License

cmakefmt is dual-licensed under MIT or Apache-2.0 at your option.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

cmakefmt-1.0.0.tar.gz (139.0 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

cmakefmt-1.0.0-py3-none-win_amd64.whl (2.8 MB view details)

Uploaded Python 3Windows x86-64

cmakefmt-1.0.0-py3-none-manylinux_2_39_x86_64.whl (2.9 MB view details)

Uploaded Python 3manylinux: glibc 2.39+ x86-64

cmakefmt-1.0.0-py3-none-manylinux_2_39_aarch64.whl (2.8 MB view details)

Uploaded Python 3manylinux: glibc 2.39+ ARM64

cmakefmt-1.0.0-py3-none-macosx_11_0_arm64.whl (2.7 MB view details)

Uploaded Python 3macOS 11.0+ ARM64

cmakefmt-1.0.0-py3-none-macosx_10_12_x86_64.whl (2.9 MB view details)

Uploaded Python 3macOS 10.12+ x86-64

File details

Details for the file cmakefmt-1.0.0.tar.gz.

File metadata

  • Download URL: cmakefmt-1.0.0.tar.gz
  • Upload date:
  • Size: 139.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for cmakefmt-1.0.0.tar.gz
Algorithm Hash digest
SHA256 4a2db66c765328dd6ea2f4d1b0465ae8fc1b6e92a2a84e04ae7e487c43570849
MD5 609bf4369db7e862d26e26e0379b3eaa
BLAKE2b-256 ec10953d3ec7d0bb27081af8bc3e40f01f63ab131a3d5d940cc8279e5c9dec7f

See more details on using hashes here.

Provenance

The following attestation bundles were made for cmakefmt-1.0.0.tar.gz:

Publisher: release.yml on cmakefmt/cmakefmt

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file cmakefmt-1.0.0-py3-none-win_amd64.whl.

File metadata

  • Download URL: cmakefmt-1.0.0-py3-none-win_amd64.whl
  • Upload date:
  • Size: 2.8 MB
  • Tags: Python 3, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for cmakefmt-1.0.0-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 53af024ba1b724b04966c043990316c58dd057f4592c2308e551461455ae32a5
MD5 5111a6f9d252b6ec623f99be3f87f362
BLAKE2b-256 3eab6b713d3d22f64fd7f96ee0d4e20c1423ec56d9f350d0017060a70ffad9cd

See more details on using hashes here.

Provenance

The following attestation bundles were made for cmakefmt-1.0.0-py3-none-win_amd64.whl:

Publisher: release.yml on cmakefmt/cmakefmt

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file cmakefmt-1.0.0-py3-none-manylinux_2_39_x86_64.whl.

File metadata

File hashes

Hashes for cmakefmt-1.0.0-py3-none-manylinux_2_39_x86_64.whl
Algorithm Hash digest
SHA256 068fb7a29f74edb6f85a4bbcf38486fc66663b74b8ba1b3902a605eb59a80ab5
MD5 ca2e8439b0ed33a9adb0d34c1ee377ef
BLAKE2b-256 0067fb0496a0c8afc3df46d46d5045e8feba124689e9ff6cb9d47c608269fc01

See more details on using hashes here.

Provenance

The following attestation bundles were made for cmakefmt-1.0.0-py3-none-manylinux_2_39_x86_64.whl:

Publisher: release.yml on cmakefmt/cmakefmt

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file cmakefmt-1.0.0-py3-none-manylinux_2_39_aarch64.whl.

File metadata

File hashes

Hashes for cmakefmt-1.0.0-py3-none-manylinux_2_39_aarch64.whl
Algorithm Hash digest
SHA256 326055de0831f1777c34f51c33fe1479be38cf1312f82f5b780c18a2e5eca59d
MD5 72fe3f363801af8e2cd92fe16be17b0a
BLAKE2b-256 0b4302d0ff9cf7c842a579764d17d52dc3297e7fc2d8e493809f7fedd5c6a51a

See more details on using hashes here.

Provenance

The following attestation bundles were made for cmakefmt-1.0.0-py3-none-manylinux_2_39_aarch64.whl:

Publisher: release.yml on cmakefmt/cmakefmt

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file cmakefmt-1.0.0-py3-none-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for cmakefmt-1.0.0-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 13450e4eabf6f35963cd188098de860f14ef894d47cc9a0fb3d6e238aa20bb9a
MD5 1db478c4033a6eca29666e330429cb7c
BLAKE2b-256 a2c99aff30c1dc34c66702721b4094c26629d759bc07fea2233532a95058e332

See more details on using hashes here.

Provenance

The following attestation bundles were made for cmakefmt-1.0.0-py3-none-macosx_11_0_arm64.whl:

Publisher: release.yml on cmakefmt/cmakefmt

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file cmakefmt-1.0.0-py3-none-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for cmakefmt-1.0.0-py3-none-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 aff425fb10ec1c1ff8eb85c50bb57890c853a159a8adb01e5119af647277f4ec
MD5 40ea0d5c0520e2f0223c971ab6c64ef1
BLAKE2b-256 58d07cdec4afea53144628f99f757229e2ccd73ad8d8691973f6995b9a950e6e

See more details on using hashes here.

Provenance

The following attestation bundles were made for cmakefmt-1.0.0-py3-none-macosx_10_12_x86_64.whl:

Publisher: release.yml on cmakefmt/cmakefmt

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page