Hello dear reader, if you ever came to this article wondering if you should format your code, you can stop reading right now, and go check my other post on that topic.
But if you are convinced that code should be formatted, and automatically formatted, first of all welcome ๐ this post is made for you (and for the future me if I need it ๐)
In this post, I am going to talk specifically about formatting C++ code, but this can be also used to format C, Java, JavaScript, Objective-C, Protobuf and C# languages.Why C++, you may ask ? For no particular reason other than this is a language I use almost daily ๐
Enough for the introduction, letโs go in the center of the subject !
How to format with C++ code ?
If you google "How to format C++ code", you will find a lot of articles and posts about tools you can use to format C++ code, which can make it difficult to choose what to do.
But there is one tool that comes back a lot of time, a tool named clang-format
, and we are going to see how to use it to format our code.
Why this one, you may wonder ?! ๐ค
Well, if you build c++ code, you have probably encountered the clang compiler, which is an open-source compiler for the C family of programming languages.I wonโt go in detail on the clang
project, but as part of this project, there is the tool clang-format
which is used to format C++ code.
That means that clang-format
is actively maintained, which is really great !Moreover, clang-format
allows you to format more that C++ code ! It currently allows you to format C, C++, Java, JavaScript, Objective-C, Protobuf and C# languages. So even if you donโt use C++, there is still a chance that this tool can be useful for you. In the rest of this article, each time I will talk about using clang-format
for formatting C++ code, you can think that it can do the same for those other languages.
It also allows you to customize the formatting to have the one you like for your projects, and you can integrate it inside a lot of others tools!
For all those reasons, letโs see how to actually use it ๐
How does it work ?
Good question ! For those who have ever use cmake-format (a tool to format Cmake code), it works almost the same way (even if clang-format
has been created before ๐).
Once installed, you can use it in your terminal like that to format a file:
clang-format -i myfile.cpp
Pretty straight forward, isnโt it ?!The option -i
allows clang-format
to write the formatted version of the Cmake file in place, which means that, after you run this command, your file is now formatted ๐
There is a lot of option available with this tool, and I wonโt go too much in details, but I invite you to look at them on his GitHub ๐
Moreover, you can create your how configuration file, that you can name .clang-format
, if you want, to specify how you want some elements to render in your C++ files in a folder.
So you can format your C++ code and customize how it will be formatted ! How awesome is that ?! ๐
You convinced me ! How do I get it on my machine, now ?
The better way to install clang-format, is to go through a package manager.Of course, you can build it from the llvm sources, but this will take a long time and probably needs its own article. So the package manager is the way to go.
And the good news is that, whatever the Operating System you are using, you can install it through a packkage manager:
-
Linux โ
apt-get install clang-format
-
Osx โ
brew install clang-format
-
Windows โ
choco install llvm
Or you can install it with pip
(https://pypi.org/project/clang-format/) on whatever system you want : pip install clang-format
.
How to automatically format a repository ?
Now that we know how to install clang-format
, and use it to format a file, letโs see how to automatically format all the C++ files of in a repository (for other language, you can use a similar method and only adapt a few characters).
If you know exactly what are the C++ files your project have and are sure that those will never change (no new files), you can only use the command line showing you how to use clang-format
to format them all.But, in most project, some files will be added, moved or removed, so we need a way to format them all, without knowing their location or their name in advance.
To do so, a simple command line can do the trick by combining the command find
and clang-format
, like that:
find . \( -name '*.hpp' -o -name '*.cpp' \) -exec clang-format -i {} \;
This command will look through all the folder and sub-folder from your current position, and look for the files with the extension .hpp
or .cpp
files. Then it will place all those files in place of the {}
and run the command clang-format -i
with all the files. If you are using other extension for the files, you can add or remove them util all the files you want to format are given to the command line !
And voilร , you have it ! One line, you can format them all ๐
And there is more !
The one line command to format all the C++ files is good, but, I must say that this is not a line easy to remember.This issue can prevent people to use it because they donโt want to go through the documentation to find it again to paste it in their terminal.And we canโt be mad at them for that, if they can, people will always resist change, so if you have such line to learn without being convinced of the benefits of formatting, you wonโt learn it.
So what to do ? We have only one line ? Can we make it simpler ?
And yes, we can ! ๐ ๐
To do so, you can create a Makefile, on the top level of your project repository, so that you will have an alias for this complicated line. This Makefile
will be as simple as that:
format:
set -f
find . \( -name '*.hpp' -o -name '*.cpp' \) -exec clang-format -i {} \;
set +f
And now, all people will have to do is to run make format
, and all the formatting will occur without them having to learn a complicated line.
This is actually more powerful than that ! If for some reason, you have to change the tool you use for formatting C++ files, all you have to do, is to modify the Makefile
, and your coworkers wonโt even be bother by it, since the command make format
will still be the thing they will have to do !Moreover, if you want, you can also add other formatting tools for other language in the Makefile
so that the command make format
formats actually all your source files, whatever their languages !!! ๐
I also have to mention that, to help to integrate it to your workflow, clang-format
can also be include in a lot of other tools, such as Vim, Emacs, BBEdit, CLion, Visual Studio, and probably a lot more if you search for them. ๐
Letโs force formatting by default !
Now, we have an easy-to-remember command than allows us to format our C++ code.Everybody is happy, and use it.Everybody, well actually no, there is this one time you forgot, and the code has been integrated to the project, and now, everybody has formatting conflicts.Or that time when the new intern didnโt know he (or she) that this command existed.Or those coworkers that want to use it, but still forgets, since they donโt have the habit yet
For all this reason, and maybe more, you should for the formatting by default.But what do I mean by that ? ๐ค
Itโs simple, you should make it impossible, or at least, very difficult for anyone to not format his code, and have this not-formatted code in be integrated in production, or even reach code reviews !
How do we do that ?Well, there is actually two things you can do.
Pre-commit hook
If you are using git
(and I hope you do version your code), you can create what is called a pre-commit hook. This is a script that is going to be executed before each of your commits, which is perfect for formatting !
Indeed, if, before any of your commits, you can format automatically your code, then, you wonโt ever forget it, or even have to thing about formatting again! ๐This is how you gain back some time to do some more important stuff: automation !!
You can find here, an exemple of pre-commit hook that may help you to have your own ๐
CI check
Another way to force the formatting of the files on your repository, is to create a check on a CI/CD system such as Travis.
If you are not familiar with the concept of Continuous Integration, I encourage you to look at it, it will truly benefit you, and your team. For those who know what a CI/CD system such as Travis is, letโs continue.
But how can we test that the files of our repository are well formatted ?Pretty easily actually, all we have to do is to implement this three steps:
- Getting
clang-format
on the system, if it is not already installed - Running the format command
make format
- Checking that the formatting didnโt change any files
If we can implement all of them, we win ๐
Actually, we already have 2 of them !We know that we can install clang-format
using pip
! This is a first win ๐
And running the command make format
is as simple as executing any other command on a CI/CD system.
So all we have left, is to check if one file as change after the formatting, which will mean that the person did not have formatted his code before the commit or the push on the CI.And there is a command line for that too ๐
git diff --exit-code
This command will check the difference for the files in your repository, and will return 0 (= success) if no change is detected, and something else (=failure) if a file has change.
And voilร , we have our 3 steps ๐
GitHub Action
To help a bit more, you will fin below this line, the content of a GitHub Action which does exactly that ! Since GitHub Actions is now available, I think that it might be easier for anyone to integrate it that way. ๐
name: C/C++ CI
on: [push]
jobs:
build:
runs-on: windows-2016
steps:
- uses: actions/checkout@v1
- name: Running cpp formatting
run: make format
- name: Checking formatting
run: git diff --exit-code
No need to install clang-format since it is already install by default on the system provided by GitHub Action \o/
Conclusion
As a conclusion, I will say that writing this article was pretty fun.I sincerely hope that you had as much fun reading it that I had writing it ๐
And that it will help you to have a better workflow (at least for the formatting part) in your code.I will write some other article to help you and myself format files of other languages.They will be out in the next weeks.
And until then, have fun learning, growing, and have a wonderful time. ๐
Top comments (1)
I like to combine Astyle (Artistic Style) with clang-format because it solves some of the limitations that clang-format has, like adding missing brackets to control statements. Clang-tidy is capable of that but it needs to be aware of compilation flags, the compilation database and so on, making it unfeasible for hooks (plus its slow).
astyle.sourceforge.net/astyle.html