Formatting C++ Code With clang-format¶
Mozilla uses the Google coding style for whitespace, which is enforced
using clang-format. A
specific version of the binary will be installed when
./mach clang-format
or ./mach bootstrap
are run. We build our
own binaries and update them as needed.
Options are explicitly defined in clang-format itself. If the options are changed in clang upstream, this might cause some changes in the Firefox tree. For this reason, it is best to use the mozilla-provided binaries.
Manual formatting¶
We provide a mach subcommand for running clang-format from the command-line. This wrapper handles ensuring the correct version of clang-format is installed and run.
If clang-format isn’t installed, the binaries will be automatically downloaded from taskcluster and installed into ~/.mozbuild. We build our own clang-format binaries.
Formatting local changes¶
$ ./mach clang-format
When run without arguments, it will run on a local diff. This could miss some reformatting (for example, when blocks are touched). (searchfox)
Formatting specific paths¶
$ ./mach clang-format -p <path> # Format <path> in-place
$ ./mach clang-format -p <path> -s # Show changes
The command also accepts a -p
argument to reformat a specific
directory or file, and a -s
flag to show the changes instead of
applying them to the working directory
(searchfox)
Formatting specific commits / revisions¶
$ ./mach clang-format -c HEAD # Format a single git commit
$ ./mach clang-format -c HEAD~~..HEAD # Format a range of git commits
$ ./mach clang-format -c . # Format a single mercurial revision
The command accepts a -c
argument that takes a revision number or
commit range, and will format the lines modified by those commits.
(searchfox)
Scripting Clang-Format¶
Clang format expects that the path being passed to it is the path
on-disk. If this is not the case, for example when formatting a
temporary file, the “real” path must be specified. This can be done with
the --assume-filename <path>
argument.
Configuring the clang-format commit hook¶
To run clang-format at commit phase, run mach boostrap
or just add
the following line in the hgrc
file:
[extensions]
clang-format = ~/.mozbuild/version-control-tools/hgext/clang-format
We use a hg extension as they are more flexible than hooks.
With git, the configuration is the following:
# From the root git directory:
$ ln -s $(pwd)/tools/lint/hooks_clang_format.py .git/hooks/pre-commit
You’ll likely need to install the python-hglib
package for your OS,
or else you may get errors like abort: No module named hglib.client!
when you try to commit.
Editor integration¶
It is possible to configure many editors to support running
clang-format
automatically on save, or when run from within the
editor.
Editor plugins¶
Eclipse
Install the CppStyle plugin
In Preferences -> C/C++ -> CppStyle, set the clang-format path to ~/.mozbuild/clang-tools/clang-tidy/bin/clang-format
(Optional) check “Run clang-format on file save”
-
clang-format.el (Or install clang-format from MELPA)
google-c-style from MELPA
Configuration¶
These tools generally run clang-format themselves, and won’t use
./mach clang-format
. The binary installed by our tooling will be
located at ~/.mozbuild/clang-tools/clang-tidy/bin/clang-format
.
You typically shouldn’t need to specify any other special configuration in your editor besides the clang-format binary. Most of the configuration that clang-format relies on for formatting is stored inside our source tree. More specifically, using the .clang-format file located in the root of the repository. Please note that this doesn’t include the list of ignored files and directories (provided by .clang-format-ignore which is a feature provided by the mach command wrapper).
Coding style configuration is done within clang-format itself. When we change the configuration (incorrect configuration, new feature in clang, etc), we use local overrides.
Ignored files & directories¶
We maintain a list of ignored directories and
files,
which is used by ./mach clang-format
. This is generally only used
for code broken by clang-format, and third-party code.
Ignored code hunks¶
Sections of code may have formatting disabled using comments. If a section must not be formatted, the following comments will disable the reformat:
// clang-format off
my code which should not be reformated
// clang-format on
You can find an example of code not formatted.
Merging formatted and unformatted code¶
During the transition to using chromium style enforced by clang-format for all code in tree, it will often be necessary to rebase non-formatted code onto a formatted tree.
Mercurial¶
The format-source
extension, now bundled with
version-control-tools
, and installed by ./mach bootstrap
, may be
used to seamlessly handle this situation. More details may be found in
this
document.
The parent changeset of the reformat has been tagged as
PRE_TREEWIDE_CLANG_FORMAT
.
Git¶
To perform a rebase onto mozilla-central after the merge, a handy merge
driver, clang-format-merge
, has been written:
$ git clone https://github.com/emilio/clang-format-merge
$ /path/to/clang-format-merge/git-wrapper rebase <upstream>
The wrapper should clean up after itself, and the clone may be deleted after the rebase is complete.
Ignore lists¶
To make sure that the blame/annotate features of Mercurial or git aren’t affected. Two files are maintained to keep track of the reformatting commits.
With Mercurial¶
# ignore-this-changeset
The syntax in this file is generated using the following syntax:
$ hg log --template '{node} - {author|person} - {desc|strip|firstline}\n'
With git¶
The list is stored in https://searchfox.org/mozilla-central/source/.git-blame-ignore-revs and contains git revisions for both gecko-dev and the git cinnabar repository.