This repo is a single source of truth for .clang-format configs. Use it by syncing the file into your project (e.g. via a small script) and running clang-format via pre-commit (e.g. mirrors-clang-format); no CMake or custom shell hooks in your tree.
clangformat/
.clang-format # optional: default/latest (e.g. copy of configs/v22/.clang-format)
configs/
v14/
.clang-format # for clang-format 14.x
v22/
.clang-format # for clang-format 22.x
- Versioned configs:
configs/v<major>/holds a.clang-formatvalid for that clang-format major. Consumers fetch the one that matches their pre-commitrev(or pick explicitly). - Root
.clang-format: Optional default for repos that don’t use the sync script or want “latest”.
Projects that use this repo typically add a small script (e.g. devenv/sync-clang-format.sh) that:
- Picks a version (script arg, env
CLANGFORMAT_VERSION, or from.pre-commit-config.yamlmirrors-clang-formatrev). - Fetches
configs/v<major>/.clang-formatfrom this repo (raw GitHub URL), or the root.clang-formatif that path doesn’t exist. - Writes it to the project root
.clang-format.
Example (run from project repo root):
./devenv/sync-clang-format.sh [VERSION]- VERSION (optional): clang-format major (e.g.
14,22). Default: from pre-commit config or22. - Override source: env
CLANGFORMAT_REPO,CLANGFORMAT_BRANCH, orCLANGFORMAT_VERSION.
Formatting is then enforced by pre-commit (e.g. pre-commit run --all-files); no need for CMake format targets or custom hooks from this repo.
- v22 (and newer): Full option set (e.g.
BreakBeforeConceptDeclarations,IndentRequiresClause,StatementAttributeLikeMacros,SeparateDefinitionBlocks,BitFieldColonSpacing,Standard: Latest). - v14: Omit options that don’t exist in 14; keep a compatible subset to avoid unknown-key noise.
When adding a new clang-format major (e.g. v23), add configs/v23/.clang-format (copy from v22 and adjust if needed). Keep the root .clang-format as a default for repos that don’t use the sync script or want “latest”.
The following way of using this repo is deprecated. Prefer the flow above: sync .clang-format into your repo and use pre-commit for formatting.
Previously, this repo was used via CMake FetchContent and a shell script (clangformat.sh) to copy the config and add format targets (e.g. “format-all”). That avoided pre-commit and relied on a fixed MB_CLANGFORMAT_VER and custom hooks in the consumer.
- Why deprecated: Pre-commit gives a single, standard way to run clang-format (and other linters) with pinned versions; no need for per-repo CMake format targets or custom scripts. Syncing only the
.clang-formatfile keeps this repo as “config only” and lets each project choose how to run clang-format (almost always via pre-commit). - If you still rely on the old integration: The root
.clang-formatand any files you already fetch (e.g.clangformat.sh, CMake snippets) may remain available for a while, but will not be improved. Prefer migrating to the sync script + pre-commit flow described above.
Continuing with the deprecated readme part...
Intended to be the single point of truth of the/a .clang-format file (C++ code auto formatting configuration). Mainly handling storage and versioning here. But there is also useful tool support for creating format-all CMake targets or applying formatting during pre-commit git hooks. See Usage section for that.
Preferred clang-format version: see MB_CLANGFORMAT_VER in CMakeLists.txt, which you can configure to be a higher version also of course. Although plain clang-format is used if the preferred version is not available.
This needs to be updated when using features in .clang-format
not supported by lower versions.
cmake_minimum_required(VERSION 3.14)
include(FetchContent)
FetchContent_Declare(mb-clangformat
GIT_REPOSITORY "https://github.com/devmarkusb/clangformat"
GIT_TAG origin/HEAD
GIT_SHALLOW ON
)
FetchContent_MakeAvailable(mb-clangformat)
# of course the copied files are not intended to be edited
file(COPY ${mb-clangformat_SOURCE_DIR}/.clang-format DESTINATION ${PROJECT_SOURCE_DIR}/)
file(COPY ${mb-clangformat_SOURCE_DIR}/clangformat.sh DESTINATION ${PROJECT_SOURCE_DIR}/
FILE_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
Then you could add
#!/usr/bin/env bash
script_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
$script_dir/../clangformat.sh
to your repo's local .githooks/pre-commit git hook file, to apply formatting on each commit automatically.
Additionally, you can include the following lines in your project's
CMakeLists.txt files, which will add a clang-format target per project.
When building the target, every file from the list of subdirs (recursively) will
be formatted.
set(cxx_dirs "apps;include;libs;sdks;source;src;test")
add_clang_format_project_target("${cxx_dirs}")
Be careful to really pass a semicolon-separated list of subdir strings.
In the example add_clang_format_project_target(${cxx_dirs}) without
quotes wouldn't work.
A directory for storing examples, other versions, or certain default styles, just for comparison.