This example shows how to call the 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
-
CMakeLists.txt - Top level CMakeLists.txt
-
.clang-format - The file describing the style guide
-
cmake/modules/FindClangFormat.cmake - Script to find the clang-format binary
-
cmake/modules/clang-format.cmake - Script to setup the format targets
-
cmake/scripts/clang-format-check-changed.py - A helper script to check against changed files in git
-
cmake/scripts/clang-format-check-changed.py - An old simplified version of the above helper script
-
subproject1/CMakeLists.txt - CMake commands for subproject 1
-
subproject1/main1.cpp - source for a subproject with no style errors
-
subproject2/CMakeLists.txt - CMake commands for subproject 2
-
subproject2/main2.cpp - source for a subproject that includes style errors
To run this example you must have clang format tool installed. This can be installed on Ubuntu using the following command.
$ sudo apt-get install clang-format-3.6
It will result in the tool being available as:
$ clang-format-3.6
If you install a different version, you can edit the CLANG_FORMAT_BIN_NAME
variable in the root CMakeLists.txt
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:
Language: Cpp
# BasedOnStyle: LLVM
AccessModifierOffset: -4
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
As mentioned, the style in this example is based on the .clang-format file. This can be changed by editing clang-format.cmake and changing
the -style=file
to the required style;
This example will setup 3 targets:
-
format
-
format-check
-
format-check-changed
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
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
set(CLANG_FORMAT_EXCLUDE_PATTERNS "build/")
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
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:
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. |