How-to Guide: clang-format
This guide is for developers who wish to apply clang-format on their chosen
development machine, whether that be their personal machine or a multi-user
cluster.
In this guide, we will describe how to configure/run clang-format on EAMxx
code and also how to install it if necessary.
Configure and Run clang-format
Running clang-format according to the defined EAMxx standard can be
done using only command line arguments; however, the command is quite long.
The easier route is to reference the configuration file
($EAMXX_ROOT/.clang-format).
In this case the command is
clang-format [-i] --style="file:${EAMXX_ROOT}/.clang-format" <path/to/c++/source/file(s)>
where the -i (--in-place) argument controls whether the formatting edits
are conducted and change the source file(s) ("in place") or the required edits
are printed to stdout (flag omitted).
Also, note that the --style flag can also fully define the options without
the configuration file as follows, but this is not recommended as the
configuration could change before this guide is updated to reflect as such.
Terminal One-(long-)liner
clang-format [-i] --style="{BasedOnStyle: llvm, ColumnLimit: 100, AlignConsecutiveAssignments: true, AlignConsecutiveBitFields: true, AlignConsecutiveMacros: true, AlignEscapedNewlines: true, AlignTrailingComments: true}" <path/to/c++/source/file(s)>
Installing clang-format
On a personal machine, which we will consider to be one for which you have
sudo privileges, installation can be conducted via package manager or by
building llvm v14 from scratch.
If you are a non-admin user of a multi-user cluster, HPC platform, etc., then
it is likely to be an easy process, though potentially not immediate.
If you require or already have multiple versions of clang-format installed
Note that, depending on your requirements, this could be placed in your shell
config file (.bashrc, .zshrc), or if only needed for a shell session, it
can be done directly from the command line.
The other option is to add a versioned symbolic link to your PATH.
This is sometimes included in the package's bin/ directory by default and,
if not, can be added there after of placed somewhere that is already on your
PATH.
$ cd /opt/homebrew/opt/llvm@14/bin
$ ls clang-format*
clang-format
// no versioned binary so we create symlink
$ ln -s ./clang-format ./clang-format-14
$ which clang-format
/opt/homebrew/opt/llvm@14/bin/clang-format-14
OR
$ cd /opt/homebrew/opt/llvm@14/bin
$ ls clang-format*
clang-format
// no versioned binary so we create symlink in a directory already on PATH
$ echo $PATH
/usr/bin:/usr/local/bin
$ ln -s ./clang-format /usr/local/bin/clang-format-14
$ which clang-format
/usr/local/bin/clang-format-14
For Mac users, the Homebrew
package manager (brew) is the quickest and most straightforward way
to get clang-format installed.
Since clang-format v14 is not available to install directly from
Homebrew, we install the entire LLVM package at version 14, and this
is as simple as
brew install llvm@14
It it likely that Homebrew will issue a message about not linking the
clang-related tools by default, so next we add the binary to our PATH.
$ export PATH="/opt/homebrew/opt/llvm@14/bin/clang-format:$PATH"
# Note: this is the default location for a recent Mac running Apple silicon.
# It may be different on another system.
# You can confirm where yours is installed via 'brew info llvm@14'
$ which clang-format
/opt/homebrew/opt/llvm@14/bin/clang-format
Note also, that if your system has multiple version of clang-format installed,
it may be preferable to instead set a versioned alias to clang-format
(clang-format-14) as in
// create a shell-alias
alias clang-format-14="/opt/homebrew/opt/llvm@14/bin/clang-format"
Given the many flavors of Linux, it is difficult to generalize, but there
is a high probability the proper version of clang-format or llvm is
provided by the built-in package manager.
The commands will differ based on your Linux distribution, but using the
Debian/Ubuntu apt syntax, it could be accomplished via something like
$ apt search clang-format
[...]
clang-format-14/...
$ apt install clang-format-14
If you do not succeed in the above, clang-format can also be fully built
from the LLVM Compiler Infrastructure.
It will begin with something like
git clone git@github.com:llvm/llvm-project.git
git checkout llvmorg-14.0.6 # version tag
Also, if you only need clang-format and not any of the other tooling,
it will build faster/smaller if you use the CMake flag
-DLLVM_ENABLE_PROJECTS="clang" to only build clang and it's friends,
rather than all of llvm.
And finally, the README for LLVM version 14.0.6
is far more comprehensive that the one for the latest version, and it contains
instructions specific to that build.
In many cases llvm, clang, or clang-format will be available as a module,
though whether version 14 is an option could be less likely.
In the optimistic case, it could be as simple as (using Lmod syntax)
$ module avail llvm # [clang, clang-format]
[... list ]
$ module load llvm/14.0.6
If it is not available, you will probably need to reach out to a system administrator to get an official version installed.1
Unnecessary but Convenient Workflow Customization (direnv)
If you'd like to add a layer of automation/complexity to ensure you only use
clang-format v14 on EAMxx and/or want to use a newer version on the rest
of your system, there is a very handy terminal tool called
direnv
(brew install direnv) that allows you to automatically load and unload
environment variables based on $PWD using a .envrc file.
As an example, here's my .envrc that adds clang-format v14 to the path
when I'm working on EAMxx.
PATH_add /opt/homebrew/opt/llvm@14/bin/clang-format
# also, since I often forget to load a python environment that's required for
# running ctest, this creates or loads a python 3 virtual environment with numpy
layout python3
pip install --upgrade pip
# the upgrade isn't strictly necessary but trades a little extra setup on
# the front end to avoid pip endlessly reminding you to update
pip install numpy
This file can be placed in the top-level EAMxx directory, and running
direnv allow enables the functionality.
Namely, executing cd EAMxx loads the defined environment that stays loaded
in any subdirectories, and resets the standard environment when exiting to a
directory above/outside of EAMxx.
For the conda fans, this tool can also be used to auto-load a
pre-configured conda environment since the .envrc is essentially a bash
script with a few bells and whistles tacked on.
-
There are rumors of using
condacreatively to do a user-install, but that is not an option we support or suggest. ↩