A CMake formatter and static analyzer
Project description
cmtk 🛠️
cmtk (CMake Toolkit) is a high-performance, schema-driven CMake code formatter and analyzer built in Rust. It utilizes a lossless Concrete Syntax Tree (CST) pipeline to guarantee that formatting operations never destroy comments, whitespace, or any other source details.
Unlike general-purpose formatters or simple regular-expression tools, cmtk formats CMake files according to known function signature schemas. It can automatically discover schemas for custom CMake functions/macros by analyzing the codebase (e.g. looking for uses of cmake_parse_arguments), allowing for precise, semantic layouts without tedious manual configuration.
Key Features
- Lossless CST Architecture: Built on top of the Rowan library (used in
rust-analyzer) and the Logos lexer. The formatting pipeline guaranteestree.to_string() == original_sourceprior to styling, meaning comments, bracket arguments, and trivia are fully preserved. - Schema-Driven Formatting: Employs structural layouts based on CMake commands' signatures. It distinguishes positional arguments, options (flags), one-value keywords, and list keywords.
- Auto-Schema Discovery: The
cmtk scansubcommand inspects your macros and functions, parsing their innercmake_parse_argumentscalls to automatically generate configuration schemas. - Advanced List Wrapping Rules:
- Packed: Packed by width (default for target names, components).
- Path: One-per-line formatting for file lists, keeping singletons inline.
- Command Arguments (
command_argv): Retains executable and initial flags on the same line, wrapping trailing arguments. - N per Line: Groups arguments into sets of
n(e.g.,n = 2for properties key-value pairs).
- Searchability Preservation: Keeps the first argument (e.g., target names in
set_target_properties, or variable names inset/option) on the opening line to maintain searchability via simple tools likegrep. - Configurable: Settings are easily configured using a
.cmtkrcfile or a[tool.cmtk]section inpyproject.toml.
Installation
Ensure you have the Rust toolchain installed. Build the project using cargo:
git clone https://github.com/halide/cmtk.git
cd cmtk
cargo build --release
The resulting binary will be available at target/release/cmtk.
Usage
cmtk provides a CLI with three subcommands: format, scan, and parse.
1. Formatting Files
To format a CMake file and print the result to stdout:
cmtk format CMakeLists.txt
To format files in-place:
cmtk format -i CMakeLists.txt src/CMakeLists.txt
To check if files are formatted (useful in CI pipelines):
cmtk format --check CMakeLists.txt
Automated Schema Discovery during Format
You can point the formatter to files containing custom definitions (--scan-only) to teach it your custom command signatures on-the-fly:
cmtk format CMakeLists.txt --scan-only cmake/MyMacros.cmake
You can also instruct it to find all CMake files in your Git repository automatically:
cmtk format CMakeLists.txt --discover=git
2. Scanning / Schema Discovery
To scan custom CMake files, extract schemas, and output them in TOML:
cmtk scan cmake/MyMacros.cmake
To write/append the scanned schemas directly to your local .cmtkrc:
cmtk scan cmake/MyMacros.cmake --write
3. Parsing (Debug representation)
To inspect the raw lossless syntax tree produced by the parser:
cmtk parse CMakeLists.txt
Formatting Style Guidelines
For multiline commands, cmtk avoids visually random continuation indentation or alignment under the opening parenthesis. Instead, it aligns the closing parenthesis with the command name and applies block indentation.
Preferred (Block Indentation)
find_package(
Halide_LLVM 21...99 REQUIRED
COMPONENTS WebAssembly X86
OPTIONAL_COMPONENTS AArch64 ARM Hexagon NVPTX PowerPC RISCV
)
List Layouts (list_type)
-
packed(Default): Packs items as long as they fit the line, wrapping them when they exceed the limit:target_link_libraries( MyTarget PUBLIC Halide_Runtime Halide_Headers Halide_Compiler Halide_Tools PRIVATE LLVMCore LLVMSupport LLVMAnalysis LLVMTarget )
-
path: Paths format one-per-line when multiple, but singletons stay inline.When there are multiple keyword blocks, they are all indented:
target_sources( MyTarget PUBLIC include/Halide.h include/HalideBuffer.h PRIVATE src/Argument.cpp src/Bounds.cpp src/Buffer.cpp )
When a list is at the end of the argument list (the last block) and no prior blocks were indented, it is flattened/de-dented to align with the keyword:
target_sources( MyTarget PRIVATE src/file1.cpp src/file2.cpp src/file3.cpp )
Similarly, if a singleton path is too long to fit inline and is in the last block, it wraps and is de-dented:
target_sources( MyTarget PRIVATE extremely/long/path/to/some/nested/source/file/that/will/definitely/exceed/the/column/limit/to/verify/the/dedented/singleton/rule.cpp )
-
n_per_line(e.g.n = 2for property pairs):set_target_properties(MyTarget PROPERTIES CXX_STANDARD 17 CXX_STANDARD_REQUIRED YES EXPORT_NAME MyTarget )
Configuration
cmtk automatically discovers configuration by searching for .cmtkrc in the current directory first, then fallback to [tool.cmtk] in pyproject.toml.
Configuration Options
| Option | Type | Default | Description |
|---|---|---|---|
indent_style |
string | "space" |
Indentation style: "space" or "tab" |
indent_width |
integer | 4 |
Indent size in spaces |
line_width |
integer | 100 |
Target column boundary for wrapping |
source_vertical_list_threshold |
integer | 3 |
Number of items in the source after which packed lists are forced vertical (-1 to disable) |
function_schemas |
table | {} |
Mappings of lowercase CMake functions to custom format schemas |
Example .cmtkrc (TOML)
indent_style = "space"
indent_width = 4
line_width = 100
source_vertical_list_threshold = 3
[function_schemas.my_custom_install]
no_break_first_argument = true
options = ["FORCE", "VERBOSE"]
one_value_keywords = ["DESTINATION", "RENAME"]
multi_value_keywords = [
{ name = "TARGETS", list_type = "packed" },
{ name = "FILES", list_type = "path" }
]
Example pyproject.toml integration
[tool.cmtk]
indent_style = "space"
indent_width = 4
line_width = 80
[tool.cmtk.function_schemas.add_halide_library]
no_break_first_argument = true
one_value_keywords = ["GENERATOR"]
multi_value_keywords = [
{ name = "SOURCES", list_type = "path" }
]
Architecture Overview
syntax.rs: Defines token and node types (SyntaxKind) vialogosderive macros and implements therowan::Languagetrait (CmakeLanguage).lexer.rs: Feeds tokens, whitespace, and comments to the parser.parser.rs: Lossless recursive-descent parser that constructs arowan::GreenNodesyntax tree.cst.rs: Strongly typed AST wrappers for raw Rowans (such asCommandNode).schema.rs: Definitions for schema representations of CMake commands.analyzer.rs: Infers custom schemas by analyzing local CMake source trees.formatter.rs: Implements the layout engine, making formatting decisions based on line widths and schemas.
Development
Run tests, check formatting, and lint with the following cargo commands:
# Run unit, integration, and golden tests
cargo test
# Force-update the golden test specs
UPDATE_GOLDENS=1 cargo test
# Verify formatting
cargo fmt -- --check
# Run lints
cargo clippy -- -D warnings
License
This project is licensed under the MIT License. See LICENSE or project files for details.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file cmtk-0.1.0-py3-none-win_amd64.whl.
File metadata
- Download URL: cmtk-0.1.0-py3-none-win_amd64.whl
- Upload date:
- Size: 943.8 kB
- Tags: Python 3, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c7ce53be0b9dadd249f9b6d616f224b8b03cdc5c0840c98a175717cc8275c407
|
|
| MD5 |
289de50ccdfcc5abbe9e3a74fe308805
|
|
| BLAKE2b-256 |
b7d37bf5f52f1567a3dd5a5c4bedb59e3732b056de8854b52093838f4ced8939
|
Provenance
The following attestation bundles were made for cmtk-0.1.0-py3-none-win_amd64.whl:
Publisher:
release.yml on halide/cmtk
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
cmtk-0.1.0-py3-none-win_amd64.whl -
Subject digest:
c7ce53be0b9dadd249f9b6d616f224b8b03cdc5c0840c98a175717cc8275c407 - Sigstore transparency entry: 1634914372
- Sigstore integration time:
-
Permalink:
halide/cmtk@59d28e306369ff933a8955675d81f12bff4f0509 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/halide
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@59d28e306369ff933a8955675d81f12bff4f0509 -
Trigger Event:
push
-
Statement type:
File details
Details for the file cmtk-0.1.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: cmtk-0.1.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 1.1 MB
- Tags: Python 3, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
357af9ece3ac0ef5719eadadc85feb886995b4f08e1d71d13b0eb5a94fc29b0b
|
|
| MD5 |
0da4d15c20432c380c3dfe85cd3cfcd5
|
|
| BLAKE2b-256 |
57c37206cd1e594eafac63710ddb3400546110393b105aefaedc706063fd45bf
|
Provenance
The following attestation bundles were made for cmtk-0.1.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:
Publisher:
release.yml on halide/cmtk
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
cmtk-0.1.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl -
Subject digest:
357af9ece3ac0ef5719eadadc85feb886995b4f08e1d71d13b0eb5a94fc29b0b - Sigstore transparency entry: 1634914011
- Sigstore integration time:
-
Permalink:
halide/cmtk@59d28e306369ff933a8955675d81f12bff4f0509 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/halide
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@59d28e306369ff933a8955675d81f12bff4f0509 -
Trigger Event:
push
-
Statement type:
File details
Details for the file cmtk-0.1.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.
File metadata
- Download URL: cmtk-0.1.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- Upload date:
- Size: 1.0 MB
- Tags: Python 3, manylinux: glibc 2.17+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
845492777391ad4d90be1b5528e8a0e9b933f4c2adf80a34f3c0b5953876d48a
|
|
| MD5 |
26aa751bb8245240cabc4ab7bc70d702
|
|
| BLAKE2b-256 |
4abc38eade6a6a7125e6348e5993520bb24e6cbc65e9838d71d5237bcf039e6a
|
Provenance
The following attestation bundles were made for cmtk-0.1.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:
Publisher:
release.yml on halide/cmtk
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
cmtk-0.1.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl -
Subject digest:
845492777391ad4d90be1b5528e8a0e9b933f4c2adf80a34f3c0b5953876d48a - Sigstore transparency entry: 1634914268
- Sigstore integration time:
-
Permalink:
halide/cmtk@59d28e306369ff933a8955675d81f12bff4f0509 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/halide
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@59d28e306369ff933a8955675d81f12bff4f0509 -
Trigger Event:
push
-
Statement type:
File details
Details for the file cmtk-0.1.0-py3-none-macosx_11_0_arm64.whl.
File metadata
- Download URL: cmtk-0.1.0-py3-none-macosx_11_0_arm64.whl
- Upload date:
- Size: 972.0 kB
- Tags: Python 3, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1cb8ba7234988e699295524ccfd17c4e3beecc08ede9a0dcf61344bdb5bbb774
|
|
| MD5 |
caf8a36257f2028aafd8a84ee5b93171
|
|
| BLAKE2b-256 |
c1706b30662b7f0c19b7d89c6bb1f36351c4362789e3140037d9e93015238934
|
Provenance
The following attestation bundles were made for cmtk-0.1.0-py3-none-macosx_11_0_arm64.whl:
Publisher:
release.yml on halide/cmtk
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
cmtk-0.1.0-py3-none-macosx_11_0_arm64.whl -
Subject digest:
1cb8ba7234988e699295524ccfd17c4e3beecc08ede9a0dcf61344bdb5bbb774 - Sigstore transparency entry: 1634914081
- Sigstore integration time:
-
Permalink:
halide/cmtk@59d28e306369ff933a8955675d81f12bff4f0509 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/halide
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@59d28e306369ff933a8955675d81f12bff4f0509 -
Trigger Event:
push
-
Statement type:
File details
Details for the file cmtk-0.1.0-py3-none-macosx_10_12_x86_64.whl.
File metadata
- Download URL: cmtk-0.1.0-py3-none-macosx_10_12_x86_64.whl
- Upload date:
- Size: 1.0 MB
- Tags: Python 3, macOS 10.12+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3174813a0bfd1ff7757fd50420b9acf321a2eda98ed03fa06aaea9bb83705aed
|
|
| MD5 |
d51a0fd09ce7dbb30591f8c61d845d08
|
|
| BLAKE2b-256 |
46c231d5af3df91c020b9c878df825ae773b7e48d99ef48f81700bea75490a90
|
Provenance
The following attestation bundles were made for cmtk-0.1.0-py3-none-macosx_10_12_x86_64.whl:
Publisher:
release.yml on halide/cmtk
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
cmtk-0.1.0-py3-none-macosx_10_12_x86_64.whl -
Subject digest:
3174813a0bfd1ff7757fd50420b9acf321a2eda98ed03fa06aaea9bb83705aed - Sigstore transparency entry: 1634914165
- Sigstore integration time:
-
Permalink:
halide/cmtk@59d28e306369ff933a8955675d81f12bff4f0509 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/halide
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@59d28e306369ff933a8955675d81f12bff4f0509 -
Trigger Event:
push
-
Statement type: