===================================== 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 # Format in-place $ ./mach clang-format -p -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 `` argument. Configuring the clang-format commit hook ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ To run clang-format at commit phase, run ``mach bootstrap`` or just add the following line in the ``hgrc`` file: .. code:: ini [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 ~~~~~~~~~~~~~~ - `Atom `__ - `BBEdit `__ - `clang-format-bbedit.applescript `__ - 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" - `Emacs `__ - `clang-format.el `__ (Or install `clang-format `__ from MELPA) - `google-c-style `__ from MELPA - `Sublime Text `__ - `alternative tool `__ - `Vim `__ - `clang-format.py `__ - `vim-clang-format `__ - `Visual Studio `__ - `llvm.org plugin `__ - `Integrated support in Visual Studio 2017 `__ - `Visual Studio Code `__ - `XCode `__ - `Script for patch reformatting `__ - `clang-format-diff.py `__ 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 reformatted // 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: .. code:: shell $ git clone https://github.com/emilio/clang-format-merge $ /path/to/clang-format-merge/git-wrapper rebase 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 ~~~~~~~~~~~~~~ | The list is stored in `https://searchfox.org/mozilla-central/source/.hg-annotate-ignore-revs `__ | Commit messages should also contain the string ``# 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.