Be more specific with clang-format suggestions.
[alexxy/gromacs.git] / docs / dev-manual / code-formatting.rst
1 .. _gmx-codeformatting:
2
3 Automatic source code formatting
4 ================================
5
6 .. highlight:: bash
7
8 The source code can be automatically formatted using clang-format or uncrustify.
9 Both are formatting tools that apply the guidelines in :doc:`formatting`.
10 Additionally, other Python scripts are used for a few other automatic
11 formatting/checking tasks.  The overview tools page contains a list of these
12 tools: :ref:`dev-formatting-tools`.
13 This page provides more details for clang-format, uncrustify and copyright scripts.
14
15 Jenkins uses these same scripts (in particular, ``clang-format.sh``,
16 ``copyright.sh`` and the ``check-source`` target) to enforce that
17 the code stays invariant under such formatting.
18
19 .. _gmx-uncrustify:
20
21 Setting up uncrustify
22 ---------------------
23
24 A patched version of uncrustify is used for |Gromacs|.  To set this up, you need
25 to do these (once):
26
27 1. Change to a directory under which you want to build uncrustify and run::
28
29      git clone -b gromacs git://github.com/rolandschulz/uncrustify.git
30      cd uncrustify
31      ./configure
32      make
33
34 2. Copy the binary ``src/uncrustify`` into a directory of your choice
35    (``/path/to/uncrustify`` below).
36
37 Alternatively, if you are running Linux, you can try whether the binary from
38 http://redmine.gromacs.org/issues/845 works for you.
39
40 In order to use the binary for ``uncrustify.sh`` and for the pre-commit hook, you
41 also need to run this in each of your |Gromacs| repositories::
42
43   git config hooks.uncrustifypath /path/to/uncrustify
44
45 Alternatively, if you just want to use ``uncrustify.sh``, you can set the
46 ``UNCRUSTIFY`` environment variable to ``/path/to/uncrustify``.
47
48 Using the pre-commit hook or git filters needs additional setup; see the
49 respective sections below.
50
51 Note that Jenkins now only allows formatting using ``clang-format``.
52
53 .. _gmx-clang-format:
54
55 Setting up clang-format
56 -----------------------
57
58 |Gromacs| formatting is enforced with clang-format 7.0.1.
59 :command:`clang-format` is one of the core *clang* tools.
60 It may be included in a *clang* or *llvm* package from your favorite packaging
61 system or you may find a standalone *clang-format* package,
62 but you should confirm that the provided command is version 7.0.1 or
63 7.1.0. Example::
64
65     $ clang-format --version
66     clang-format version 7.1.0 (tags/RELEASE_710/final)
67
68 If you use a different version of clang-format,
69 you will likely get different formatting results than
70 the |Gromacs| continuous integration testing system,
71 and the commits that you push will fail the automated tests.
72
73 .. note::
74
75     Refer to `LLVM <http://releases.llvm.org/download.html#7.1.0>`__ for
76     source and binary downloads.
77     If downloading sources, note that you will need to download both the
78     *LLVM source code* and the *Clang source code*.
79     As per the clang
80     `INSTALL.txt <https://github.com/llvm/llvm-project/blob/release/7.x/clang/INSTALL.txt>`__,
81     place the expanded clang source into a :file:`tools/clang` subdirectory within
82     the expanded llvm archive, then run CMake against the llvm source directory.
83
84 .. todo::
85
86     Consider referencing or providing binary packages and/or checking/managing
87     the executable from an :file:`admin/` script.
88     Reference: https://github.com/mongodb/mongo/blob/master/buildscripts/clang_format.py
89
90 In order to use the installed version of clang-format for ``clang-format.sh``
91 and for the pre-commit hook, you also need to run this in each of your |Gromacs| repositories::
92
93   git config hooks.clangformatpath /path/to/clang-format
94
95 Alternatively, if you just want to use ``clang-format.sh``, you can set the
96 ``CLANG_FORMAT`` environment variable to ``/path/to/clang-format``.
97
98 As above, see the sections below for using the pre-commit hook or git filters.
99
100 clang-format discovers which formatting rules to apply from the
101 :file:`.clang-format` configuration file(s) in project directories,
102 which will be automatically updated (if necessary) when you :command:`git pull`
103 from the |Gromacs| repository.
104 For more about the tool and the :file:`.clang-format` configuration file,
105 visit https://releases.llvm.org/7.0.1/tools/clang/docs/ClangFormat.html
106
107 What is automatically formatted?
108 --------------------------------
109
110 To identify which files are subject to automatic formatting, the scripts use
111 git filters, specified in ``.gitattributes`` files.  Only files that have the
112 attribute ``filter`` set to one of the below values are processed:
113
114 - ``filter=complete_formatting``: Performs all formatting. Uses clang-format for code formatting.
115 - ``filter=uncrustify``: uncrustify is run. Deprecated and here for historical reasons.
116 - ``filter=clangformat``: clang-format is run.
117 - ``filter=includesort``: include order is enforced and copyright headers are checked.
118 - ``filter=copyright``: only copyright headers are checked.
119
120 Other files are ignored by ``uncrustify.sh``, ``clang-format.sh``,
121 ``copyright.sh`` and ``reformat_all.sh`` scripts (see below).
122
123
124 Scripts
125 -------
126
127 ``copyright.py``
128 ^^^^^^^^^^^^^^^^
129
130 This script provides low-level functionality to check and update copyright
131 headers in C/C++ source files, as well as in several other types of files like
132 CMake and Python scripts.
133
134 This file is also used as a loadable Python module for kernel generators, and
135 provides the functionality to generate conformant copyright headers for such
136 scripts.
137
138 The script is similar to uncrustify in that there is rarely need to run it
139 directly, but instead the bash scripts below use it internally.  You can run
140 the script with ``--help`` option if you want to see what all options it provides
141 if you need to do some maintenance on the copyright headers themselves.
142
143 ``uncrustify.sh``
144 ^^^^^^^^^^^^^^^^^
145
146 The information for ``uncrustify`` is mainly provided for historical reasons,
147 as the actual code formatting is now done using ``clang-format``.
148
149 This script runs ``uncrustify`` on modified files and reports/applies the results.
150 By default, the current HEAD commit is compared to the work tree,
151 and files that
152
153 1. are different between these two trees and
154 2. change under uncrustify
155
156 are reported.  This behavior can be changed by
157
158 1. Specifying an ``--rev=REV`` argument, which uses ``REV`` instead of HEAD as
159    the base of the comparison.  A typical use case is to specify ``--rev=HEAD^``
160    to check the HEAD commit.
161 2. Specifying an action:
162
163    - ``check-*``:   reports the files that uncrustify changes
164    - ``diff-*``:    prints the actual diff of what would change
165    - ``update-*``:  applies the changes to the repository
166    - ``*-workdir``: operates on the working directory (files on disk)
167    - ``*-index``:   operates on the index of the repository
168
169    For convenience, if you omit the workdir/index suffix, workdir is assumed
170    (i.e., ``diff`` equals ``diff-workdir``).
171 3. Specifying ``--uncrustify=off``, which does not run uncrustify.
172
173 By default, ``update-*`` refuses to update dirty files (i.e., that differ
174 between the disk and the index) to make it easy to revert the changes.
175 This can be overridden by adding a ``-f``/``--force`` option.
176
177 ``copyright.sh``
178 ^^^^^^^^^^^^^^^^
179
180 This script runs ``copyright.py`` on modified files and reports/applies the results.
181 By default, the current HEAD commit is compared to the work tree,
182 and files that
183
184 1. are different between these two trees and
185 2. change under have outdated copyright header
186
187 are reported.  This behavior can be changed by
188
189 1. Specifying an ``--rev=REV`` argument, which uses ``REV`` instead of HEAD as
190    the base of the comparison.  A typical use case is to specify ``--rev=HEAD^``
191    to check the HEAD commit.
192 2. Specifying ``--copyright=<mode>``, which alters the level of copyright
193    checking is done:
194
195    ``off``
196      does not check copyright headers at all
197    ``year``
198      only update copyright year in new-format copyright headers
199    ``add``
200      in addition to ``year``, add copyright headers to files that do not
201      have any
202    ``update``
203      in addition to ``year`` and ``add``, also update new-format copyright
204      headers if they are broken or outdated
205    ``replace``
206      replace any copyright header with a new-format copyright header
207    ``full``
208      do all of the above
209
210 By default, ``update-*`` refuses to update dirty files (i.e., that differ
211 between the disk and the index) to make it easy to revert the changes.
212 This can be overridden by adding a ``-f``/``--force`` option.
213
214 ``clang-format.sh``
215 ^^^^^^^^^^^^^^^^^^^
216
217 This script runs ``clang-format`` on modified files and reports/applies the results.
218 By default, the current HEAD commit is compared to the work tree,
219 and files that
220
221 1. are different between these two trees and
222 2. change under clang-format
223
224 are reported.  This behavior can be changed by
225
226 1. Specifying an ``--rev=REV`` argument, which uses ``REV`` instead of HEAD as
227    the base of the comparison.  A typical use case is to specify ``--rev=HEAD^``
228    to check the HEAD commit.
229 2. Specifying an action:
230
231    - ``check-*``:   reports the files that uncrustify changes
232    - ``diff-*``:    prints the actual diff of what would change
233    - ``update-*``:  applies the changes to the repository
234    - ``*-workdir``: operates on the working directory (files on disk)
235    - ``*-index``:   operates on the index of the repository
236
237    For convenience, if you omit the workdir/index suffix, workdir is assumed
238    (i.e., ``diff`` equals ``diff-workdir``).
239 3. Specifying ``--format=off``, which does not run clang-format.
240
241 By default, ``update-*`` refuses to update dirty files (i.e., that differ
242 between the disk and the index) to make it easy to revert the changes.
243 This can be overridden by adding a ``-f``/``--force`` option.
244
245 git pre-commit hook
246 ^^^^^^^^^^^^^^^^^^^
247
248 If you want to run ``uncrustify.sh``, ``copyright.sh`` and/or
249 ``clang-format.sh`` automatically for changes you make, you can
250 configure a pre-commit hook using ``admin/git-pre-commit``:
251
252 1. Copy the ``git-pre-commit`` script to .git/hooks/pre-commit.
253 2. Specify the path to uncrustify for the hook if you have not already done
254    so::
255
256      git config hooks.uncrustifypath /path/to/uncrustify
257
258 3. Set the operation mode for the hook::
259
260      git config hooks.uncrustifymode check
261      git config hooks.copyrightmode  update
262
263 For ``clang-format``, follow these steps instead:
264
265 1. Specify the path to ``clang-format`` for the hook if you have not already done
266    so::
267
268      git config hooks.clangformatpath /path/to/clang-format
269
270 2. Set the operation mode for the hook::
271
272      git config hooks.clangformatmode check
273
274 With this configuration, all source files modified in the commit are run
275 through the respective code formatting tool and checked for correct copyright headers.
276 If any file would be changed by ``uncrustify.sh``, ``clang-format.sh`` or ``copyright.sh``,
277 the names of those files are reported and the commit is prevented.
278 The issues can be fixed by running the scripts manually.
279
280 To disable the hook without removing the ``pre-commit`` file, you can set ::
281
282   git config hooks.uncrustifymode off
283   git config hooks.copyrightmode off
284   git config hooks.clangformatmode off
285
286 To disable it temporarily for a commit, set NO_FORMAT_CHECK environment
287 variable.  For example, ::
288
289     NO_FORMAT_CHECK=1 git commit -a
290
291 You can also run ``git commit --no-verify``, but that also disables other hooks,
292 such as the Change-Id ``commit-msg`` hook used by Gerrit.
293
294 Note that when you run ``git commit --amend``, the hook is only run for the
295 changes that are getting amended, not for the whole commit.  During a rebase,
296 the hook is not run.
297
298 The actual work is done by the ``admin/uncrustify.sh``, ``admin/clang-format.sh``
299 and ``admin/copyright.sh`` scripts, which get run with the ``check-index`` action,
300 and with ``--uncrustify``, ``--copyright`` and ``--format`` getting set according
301 to the ``git config`` settings.
302
303 ``reformat_all.sh``
304 ^^^^^^^^^^^^^^^^^^^
305
306 This script runs uncrustify, clang-format, ``copyright.py``, or the include sorter for all
307 applicable files in the source tree.  See ``reformat_all.sh -h`` for the
308 invocation.
309
310 The script can also produce the list of files for which these commands would be
311 run.  To do this, specify ``list-files`` on the command line and use
312 ``--filter=<type>`` to specify which command to get the file list for.  This can
313 be used together with, e.g., ``xargs`` to run other scripts on the same set of
314 files.
315
316 For all the operations, it is also possible to apply patters (of the same style
317 that various git commands accept, i.e., ``src/*.cpp`` matches all ``.cpp`` files
318 recursively under ``src/``).  The patterns can be specified with
319 ``--pattern=<pattern>``, and multiple ``--pattern`` arguments can be given.
320
321 As with ``uncrustify.sh``, ``-f``/``--force`` is necessary if the working tree and
322 the git index do not match.
323
324
325 Using git filters
326 -----------------
327
328 An alternative to using a pre-commit hook to automatically apply uncrustify or
329 clang-format on changes is to use a git filter (does not require either of the scripts,
330 only the ``.gitattributes`` file).  You can run ::
331
332   git config filter.complete_formatting.clean \
333       "/path/to/uncrustify -c admin/uncrustify.cfg -q -l cpp"
334   git config filter.clangformat.clean \
335       "/path/to/clang-format -i"
336
337 To configure a filter for all files that specify ``filter=complete_formatting`` attribute
338 that indicates that all formatting steps should be performed.
339
340 The pre-commit hook + manually running the scripts gives better/more
341 intuitive control (with the filter, it is possible to have a work tree that is
342 different from HEAD and still have an empty ``git diff``) and provides better
343 performance for changes that modify many files.  It is the only way that
344 currently also checks the copyright headers.
345
346 The filter allows one to transparently merge branches that have not been run
347 through the source checkers, and is applied more consistently (the pre-commit hook is
348 not run for every commit, e.g., during a rebase).