clang-format Wrapper Script Examples

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

exit 0

exit 0

Further Reading