Introduction
If you ever came to this article wondering if you should format your CMake files, 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 me in the future if I need it).
In this post, I am going to talk specifically about formatting Cmake code. Why Cmake, you may ask? For no particular reason other than this is a language I use almost daily.
Enough for the introduction, let’s go to the center of the subject!
How to Format with Cmake Code ?
If you Google "How to format Cmake code", you won’t find a lot of solutions.
Indeed, there aren’t a lot of programs that allow you to do it. But luckily for us, someone has created a program to do to exactly that, and it works pretty well and is still maintained!
This program is named cmake-format
and its source code can be found on GitHub if you want to look at it.
How Does It Work?
Good question! For those who have ever used clang-format
(a tool to format C, C++ and other kind of code), it works almost the same way.
Once installed, you can use it in your terminal like that to format a file:
cmake-format -i myfile.cmake
Pretty straight forward, isn’t it ?! The option -i
allows cmake-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 are a lot of options available with this tool, and I won’t go into too much in detail, but I invite you to look at them on his GitHub.
Moreover, you can create your how configuration file, that you can name .cmake-format.json for example, if you want, to specify how you want some elements to render in your Cmake files in a folder.
So you can format your Cmake code and customize how it will be formatted ! How awesome is that ?!
You Convinced Me ! How Do I Get It on My Machine, Now ?
Tell me if this reminds you sometimes: You found a great tool, it does everything you want, but after two hours, you still have been able to install it or to make it work on your machine…
Sounds familiar? For me, it does.
But it is not the case of this tool ! \o/ All you have to do, is to install it with pip, the package installer for Python. If you are not familiar with pip, I really encourage you to check it! It will become really helpful if you need to create a script to automate some task, for example.
How to Automatically Format a Repository?
Now that we know how to install cmake-format
, and use it to format a file, let’s see how to automatically format all the Cmake files in a repository.
If you know exactly what Cmake files your project has and are sure that those will never change (no new files), you can only use the command line showing you how to use cmake-format
to format them all. But, in most projects, 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 cmake-format
, like that:
find . \( -name '*.cmake' -o -name 'CMakeLists.txt' \) -exec cmake-format -i {} \;
This command will look through all the folders and sub-folders from your current position, and look for the files with the extension ".cmake" or for the CMakeLists.txt files. Then it will place all those files in place of the {}
and run the command cmake-format -i
with all the files.
And voilà, you have it ! One line, you can format them all.
And There Is More!
The one line command to format all the Cmake files is good, but, I must say that this is not a line easy to remember. This issue can prevent people from using 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 '*.cmake' -o -name 'CMakeLists.txt' \) -exec cmake-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 Cmake files, all you have to do, is to modify the Makefile
, and your coworkers won’t even be bothered 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, there is a Visual Studio Code extension, and a Sublime Text extension for cmake-format
. This can help you, but if one of your collaborators doesn’t use those text editors, they won’t be able to enjoy those extensions.
Let’s Force Format by Default!
Now, we have an easy-to-remember command than allows us to format our Cmake code. Everybody is happy, and uses 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 that this command existed. Or those coworkers that want to use it, but still forget, since they don’t have the habit yet.
For all these reasons, and maybe more, you should do 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 be integrated in production, or even reach code reviews !
How do we do that ? Well, there are 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 automatically format your code, then, you won’t ever forget it, or even have to think about formatting again! This is how you gain back some time to do some more important stuff: automation !!
The author of the cmake-format
repository has even been kind enough to give you a pre-commit ready to use! So nice of him !
You can find it here.
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 these three steps:
- Getting
cmake-format
on the system - 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 cmake-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 has changed after the formatting, which will mean that the person did not format 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.
To help a bit more, you will find 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: Installing dependency
run: |
python -m pip install --upgrade pip
pip install cmake_format
- name: Running cmake formatting
run: make format
- name: Checking formatting
run: git diff --exit-code
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.
History
- 15th November, 2019: Initial version