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.0-py3-none-win_amd64.whl (929.0 kB view details)

Uploaded Python 3Windows x86-64

cmtk-0.2.0-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.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (1.0 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ ARM64

cmtk-0.2.0-py3-none-macosx_11_0_arm64.whl (953.5 kB view details)

Uploaded Python 3macOS 11.0+ ARM64

cmtk-0.2.0-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.0-py3-none-win_amd64.whl.

File metadata

  • Download URL: cmtk-0.2.0-py3-none-win_amd64.whl
  • Upload date:
  • Size: 929.0 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.0-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 024390a428dbaeb47508cbffcaa589fad77001acae68d476290ed76cf20d5d70
MD5 b855623d75dbd672e27b8eb185b85321
BLAKE2b-256 acd7f458a5fbd55faf5322275eb13859ecb301014e38ecef195fe50b0952c64d

See more details on using hashes here.

Provenance

The following attestation bundles were made for cmtk-0.2.0-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.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for cmtk-0.2.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 4a7a3664a688fb910b8a93b4ded037e18a2d5467a5705937f588da8ac85728cd
MD5 ad2b4105fbacbd374900a8487000b342
BLAKE2b-256 251a6bf643b167e6fe8fe63dcdfa095f2b30991133338719b744961a1c9d0dda

See more details on using hashes here.

Provenance

The following attestation bundles were made for cmtk-0.2.0-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.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for cmtk-0.2.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 30105f0a844408161ee8ba85052c3da91dc0b3eb969e847506a9e4d3cf77a8f9
MD5 9abe5f423317d40409eee4e52e4cc242
BLAKE2b-256 01cc2aec5b5974068b74cbfa4cb61a2fbe0e34201f0540db7e26ffa35896b6c6

See more details on using hashes here.

Provenance

The following attestation bundles were made for cmtk-0.2.0-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.0-py3-none-macosx_11_0_arm64.whl.

File metadata

  • Download URL: cmtk-0.2.0-py3-none-macosx_11_0_arm64.whl
  • Upload date:
  • Size: 953.5 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.0-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 b81b1ccbaaf2f29faa6f3f308b693f9a0dbb88df1eaf62953bf7ed7f95468577
MD5 21c7d2874913fc10dd523971c8980666
BLAKE2b-256 c5e711dab8438f15f9ffd9e4253536731c0cefa3f843f3ec2d198c83124c9ad9

See more details on using hashes here.

Provenance

The following attestation bundles were made for cmtk-0.2.0-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.0-py3-none-macosx_10_12_x86_64.whl.

File metadata

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

File hashes

Hashes for cmtk-0.2.0-py3-none-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 dd42247806360834e1146d379a06a12f4881e114579a1f34c6ea9609e7542bca
MD5 fa5ff4d167748c6abb9d3ed983ab2b94
BLAKE2b-256 b902e8950c54bcab3f86664b5ff7e746fd1758f211b06e4ddf65602d8c40736c

See more details on using hashes here.

Provenance

The following attestation bundles were made for cmtk-0.2.0-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

0.2.1

5 files

This release

0.2.0 This release

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