We recently learned how to use clang-format
and created our own formatting style.
Today I’d like to show you some of the scripts I use to wrap clang-format
for different purposes. For any non-trivial use of clang-format
, you probably want to use a wrapper.
Some Notes on Options
You’ll see some common arguments used in the script samples below, so I want to explain them up front.
The style
argument below always indicates that I want to pull my formatting rules from the .clang-format
file in my repository:
-style=file
I use the in-place argument to indicate that I want files to be modified:
-i
I also set the fallback-style
to none
so that clang-format
will fail if there is no .clang-format
file in the tree.
-fallback-style=none
Formatting all C and C++ Files in a Repo
In this example, I use the find
command to get all the .h
, .c
, .hpp
, and .cpp
files in my tree. The list of files is then passed to clang-format
.
#!/bin/bash
find . -iname *.h -o -iname *.c -o -iname *.cpp -o -iname *.hpp \
| xargs clang-format -style=file -i -fallback-style=none
exit 0
Formatting all C and C++ Files in a Repo, with Exclusions
In this example, I supply a list of directory paths to find
that I want excluded from my list. This is useful for handling parts of the source tree that you don’t want to reformat, such as external libraries.
#!/bin/bash
find . -type d \( -path ./lib/external -o -path ./os -o -path ./lib/libc -o -path ./lib/libmemory \) -prune \
-o -iname *.h -o -iname *.c -o -iname *.cpp -o -iname *.hpp \
| xargs clang-format -style=file -i -fallback-style=none
exit 0
Formatting all C and C++ Files in a Directory
This example uses the find
command with a directory name supplied as a script argument. All source files in that directory will be formatted.
#!/bin/bash
if [ -z "$1" ]
then
echo "Please supply a directory or path with this script."
exit 1
fi
find $1 -iname *.h -o -iname *.c -o -iname *.cpp -o -iname *.hpp \
| xargs clang-format -style=file -i -fallback-style=none
exit 0
Format a List of Files (Supplied as Arguments)
This example allows you to provide a list of files as an argument to the script. Arguments are simply forwarded to clang-format
.
#!/bin/bash
# This script propagates all arguments to the clang-format command
clang-format -style=file -i -fallback-style=none $@
exit 0
Format Files in a git diff
This example gets the list of modified files from git ls-files
and formats them. This is a useful script to run as a pre-commit exercise.
#!/bin/bash
clang-format -style=file -fallback-style=none -i `git ls-files -om "*.[ch]" "*.[hc]pp"`
exit 0
Run clang-format
and Create a Patch
This example is used by my continuous integration build to verify formatting compliance. After clang-format
is run, we use git diff
to generate a patch file. If the file is empty, formatting is OK and we delete the file. The build server uses the presence of the patch file to determine if formatting should pass or fail.
#!/bin/bash
find . -iname *.h -o -iname *.c -o -iname *.cpp -o -iname *.hpp \
| xargs clang-format -style=file -i -fallback-style=none
git diff > clang_format.patch
# Delete if 0 size
if [ ! -s clang_format.patch ]
then
rm clang_format.patch
fi<br /><br />exit 0
Further Reading
- Creating and Enforcing a Coding Standard with
clang-format
- A Strategy for Enforcing Formatting with Your Build Server
- Automated Software Quality Enforcement course
Automated Software Quality Enforcement
The pressure on software teams is increasing – we’re expected to produce increasingly complex systems with smaller teams and on tight deadlines. We need to invest in processes that increase our team’s effectiveness so we can stay afloat. Our course teaches you how you can leverage tooling and automation to increase your team’s effectiveness – and to catch errors as early as possible.
Learn More on the Course Page