Skip to main content

cmtk 🛠️

Rust License: MIT

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 guarantees tree.to_string() == original_source prior 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 scan subcommand inspects your macros and functions, parsing their inner cmake_parse_arguments calls 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 = 2 for properties key-value pairs).
  • Searchability Preservation: Keeps the first argument (e.g., target names in set_target_properties, or variable names in set / option) on the opening line to maintain searchability via simple tools like grep.
  • Configurable: Settings are easily configured using a .cmtkrc file or a [tool.cmtk] section in pyproject.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 = 2 for 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

  1. syntax.rs: Defines token and node types (SyntaxKind) via logos derive macros and implements the rowan::Language trait (CmakeLanguage).
  2. lexer.rs: Feeds tokens, whitespace, and comments to the parser.
  3. parser.rs: Lossless recursive-descent parser that constructs a rowan::GreenNode syntax tree.
  4. cst.rs: Strongly typed AST wrappers for raw Rowans (such as CommandNode).
  5. schema.rs: Definitions for schema representations of CMake commands.
  6. analyzer.rs: Infers custom schemas by analyzing local CMake source trees.
  7. 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.

Download files

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

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

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

cmtk-0.2.1-py3-none-win_amd64.whl (929.1 kB view details)

Uploaded Python 3Windows x86-64

cmtk-0.2.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.0 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ x86-64

cmtk-0.2.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (1.0 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ ARM64

cmtk-0.2.1-py3-none-macosx_11_0_arm64.whl (953.7 kB view details)

Uploaded Python 3macOS 11.0+ ARM64

cmtk-0.2.1-py3-none-macosx_10_12_x86_64.whl (1.0 MB view details)

Uploaded Python 3macOS 10.12+ x86-64

File details

Details for the file cmtk-0.2.1-py3-none-win_amd64.whl.

File metadata

  • Download URL: cmtk-0.2.1-py3-none-win_amd64.whl
  • Upload date:
  • Size: 929.1 kB
  • Tags: Python 3, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for cmtk-0.2.1-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 f6fe6b134f1fd3215021c700e0af4949c183e3c6e216fc71d3969e9de0a20f4d
MD5 9b595c52e2fc7db61203e06c9b44744d
BLAKE2b-256 914e6952228778aea65410fba04a9eedebdab387df01b5a78a4d971d6662df18

See more details on using hashes here.

Provenance

The following attestation bundles were made for cmtk-0.2.1-py3-none-win_amd64.whl:

Publisher: release.yml on halide/cmtk

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

File details

Details for the file cmtk-0.2.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for cmtk-0.2.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 18a08b115749d57855a39dc8a452c7054c725415302985a9409ce82905f7d6d7
MD5 8cdf1f8a39cfe8c26e3102f74d87a620
BLAKE2b-256 6b294b408b35f77adc7ea6ce6158a94917d1126a3a29424d7aee67c41b18d0fd

See more details on using hashes here.

Provenance

The following attestation bundles were made for cmtk-0.2.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: release.yml on halide/cmtk

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

File details

Details for the file cmtk-0.2.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for cmtk-0.2.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 6cee09320fbd6b4f01b3154c7a6375471860089d76982ea7dc155514aaacee85
MD5 e5f2355236487af00e6331a36bb673bf
BLAKE2b-256 a29c9e64593a9adf25c2e582dfa73a11d3493ce1b82052e26b46f370e2c46558

See more details on using hashes here.

Provenance

The following attestation bundles were made for cmtk-0.2.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: release.yml on halide/cmtk

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

File details

Details for the file cmtk-0.2.1-py3-none-macosx_11_0_arm64.whl.

File metadata

  • Download URL: cmtk-0.2.1-py3-none-macosx_11_0_arm64.whl
  • Upload date:
  • Size: 953.7 kB
  • Tags: Python 3, macOS 11.0+ ARM64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for cmtk-0.2.1-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 32a55006d77004208d4dbcb57cc0e468303cf5fcbc51191abf5b451c2f591489
MD5 0e24bf0ed8c4f152cbd244cd58296e87
BLAKE2b-256 36bf3ba60c0fd369db124ffe011ff3ae2ecc3f519bb8016e54264ef78ce67f5d

See more details on using hashes here.

Provenance

The following attestation bundles were made for cmtk-0.2.1-py3-none-macosx_11_0_arm64.whl:

Publisher: release.yml on halide/cmtk

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

File details

Details for the file cmtk-0.2.1-py3-none-macosx_10_12_x86_64.whl.

File metadata

  • Download URL: cmtk-0.2.1-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/7.0.0 CPython/3.13.14

File hashes

Hashes for cmtk-0.2.1-py3-none-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 8fc5c01189b749ef36507fcbfff5d8d9c7a97fccf033f6b62744297d1319be3f
MD5 f4dd00aff73e963deebcdf1440790e1b
BLAKE2b-256 047be42d9c336ca33b8bf00d44cc1722bb16b7b52c4704078c55b2b5d0599935

See more details on using hashes here.

Provenance

The following attestation bundles were made for cmtk-0.2.1-py3-none-macosx_10_12_x86_64.whl:

Publisher: release.yml on halide/cmtk

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

Release history Release notifications | RSS feed

This release

0.2.1 This release

5 files

0.2.0

5 files

0.1.0

5 files

Supported by

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