mirror of
https://github.com/ttroy50/cmake-examples.git
synced 2025-12-18 20:24:35 +03:00
153 lines
5.0 KiB
Plaintext
153 lines
5.0 KiB
Plaintext
= clang-format
|
|
:toc:
|
|
:toc-placement!:
|
|
|
|
toc::[]
|
|
|
|
# Introduction
|
|
|
|
This example shows how to call the
|
|
https://clang.llvm.org/docs/ClangFormat.html[Clang Format] to check if your source code
|
|
matches against your code style guidelines.
|
|
|
|
The files included in this example are:
|
|
|
|
```
|
|
$ tree
|
|
.
|
|
├── .clang-format
|
|
├── CMakeLists.txt
|
|
├── cmake
|
|
│ ├── modules
|
|
│ │ ├── clang-format.cmake
|
|
│ │ └── FindClangFormat.cmake
|
|
│ └── scripts
|
|
│ └── clang-format-check-changed
|
|
├── subproject1
|
|
│ ├── CMakeLists.txt
|
|
│ └── main1.cpp
|
|
└── subproject2
|
|
├── CMakeLists.txt
|
|
└── main2.cpp
|
|
```
|
|
|
|
* link:CMakeLists.txt[] - Top level CMakeLists.txt
|
|
* link:.clang-format[] - The file describing the style guide
|
|
* link:cmake/modules/FindClangFormat.cmake[] - Script to find the clang-format binary
|
|
* link:cmake/modules/clang-format.cmake[] - Script to setup the format targets
|
|
* link:cmake/scripts/clang-format-check-changed.py[] - A helper script to check against changed files in git
|
|
* link:cmake/scripts/clang-format-check-changed.py[] - An old simplified version of the above helper script
|
|
* link:subproject1/CMakeLists.txt[] - CMake commands for subproject 1
|
|
* link:subproject1/main1.cpp[] - source for a subproject with no style errors
|
|
* link:subproject2/CMakeLists.txt[] - CMake commands for subproject 2
|
|
* link:subproject2/main2.cpp[] - source for a subproject that includes style errors
|
|
|
|
# Requirements
|
|
|
|
To run this example you must have clang format tool installed. This can be installed on Ubuntu using the following command.
|
|
|
|
[source,bash]
|
|
----
|
|
$ sudo apt-get install clang-format-3.6
|
|
----
|
|
|
|
It will result in the tool being available as:
|
|
|
|
[source,bash]
|
|
----
|
|
$ clang-format-3.6
|
|
----
|
|
|
|
If you install a different version, you can edit the `CLANG_FORMAT_BIN_NAME` variable in the root CMakeLists.txt
|
|
|
|
# Concepts
|
|
|
|
## clang-format
|
|
|
|
+clang-format+ can scan a source file then find and optionally format it to match your
|
|
companys style guidelines. There are default styles build in but you can also setup a style guide using a custom file called +.clang-format+, for example a snipped from this
|
|
repositories +.clang-format+ is below:
|
|
|
|
[source]
|
|
----
|
|
Language: Cpp
|
|
# BasedOnStyle: LLVM
|
|
AccessModifierOffset: -4
|
|
AlignAfterOpenBracket: Align
|
|
AlignConsecutiveAssignments: false
|
|
AlignConsecutiveDeclarations: false
|
|
----
|
|
|
|
## format style
|
|
|
|
As mentioned, the style in this example is based on the +.clang-format+ file. This can be changed by editing link:cmake/modules/clang-format.cmake[clang-format.cmake] and changing
|
|
the `-style=file` to the required style;
|
|
|
|
# Targets
|
|
|
|
This example will setup 3 targets:
|
|
|
|
* format
|
|
* format-check
|
|
* format-check-changed
|
|
|
|
## format
|
|
|
|
The format target will find any C++ source files and in place modify them to match the
|
|
+.clang-format+ style. The source files are found using the following cmake code
|
|
|
|
[source,cmake]
|
|
----
|
|
file(GLOB_RECURSE ALL_SOURCE_FILES *.cpp *.h *.cxx *.hxx *.hpp *.cc *.ipp)
|
|
|
|
# Don't include some common build folders
|
|
set(CLANG_FORMAT_EXCLUDE_PATTERNS ${CLANG_FORMAT_EXCLUDE_PATTERNS} "/CMakeFiles/" "cmake")
|
|
|
|
# get all project files file
|
|
foreach (SOURCE_FILE ${ALL_SOURCE_FILES})
|
|
foreach (EXCLUDE_PATTERN ${CLANG_FORMAT_EXCLUDE_PATTERNS})
|
|
string(FIND ${SOURCE_FILE} ${EXCLUDE_PATTERN} EXCLUDE_FOUND)
|
|
if (NOT ${EXCLUDE_FOUND} EQUAL -1)
|
|
list(REMOVE_ITEM ALL_SOURCE_FILES ${SOURCE_FILE})
|
|
endif ()
|
|
endforeach ()
|
|
endforeach ()
|
|
----
|
|
|
|
This will find files matching the common C++ suffixes and then remove any that match some
|
|
common CMake directories.
|
|
|
|
In the root `CMakeList.txt` we also exclude the build directory by adding the line
|
|
|
|
[source,cmake]
|
|
----
|
|
set(CLANG_FORMAT_EXCLUDE_PATTERNS "build/")
|
|
----
|
|
|
|
## format-check
|
|
|
|
This target will work as above but instead of formatting the files it will cause a failure
|
|
if any files don't match the clang-format style
|
|
|
|
## format-check-changed
|
|
|
|
This target will check the output of `git status` and scan the files to check if they match the style. This can be used by developers to make sure their changed files match the correct style.
|
|
|
|
In this example the actual check is done with a helper script +clang-format-check-changed.py+. This script will run `git status --porcelain --ignore-submodules`
|
|
to get a list of changed files, match them against the allowed extensions from the above list, and finally remove any
|
|
that match the exclude pattern from +CLANG_FORMAT_EXCLUDE_PATTERNS+. It will then run these files through clang-format and
|
|
exit with an error if the files do not match the style.
|
|
|
|
An example call to the +clang-format-check-changed.py+ script is:
|
|
|
|
[source,bash]
|
|
----
|
|
cmake/scripts/clang-format-check-changed.py --file-extensions ".cpp,*.cpp,*.h,*.cxx,*.hxx,*.hpp,*.cc,*.ipp" --exclude=build/ --exclude=/CMakeFiles/ --exclude=cmake --clang-format-bin /usr/bin/clang-format-3.6
|
|
----
|
|
|
|
[NOTE]
|
|
====
|
|
This will include all changed files in your git repository that match the patterns. In this example repository this can include files that
|
|
are part of different examples.
|
|
====
|