Merge 'origin/release-2019' into release-2020
[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 You only need a recent (at least version 7) install of the
59 `clang-tools <https://clang.llvm.org/docs/ClangTools.html>`__ to use the script.
60 Jenkins currently uses clang-format-7 to perform the task, with the style
61 encoded in the ``.clang-format`` configuration file in the top of the source
62 directory.
63
64 In order to use the installed version of clang-format for ``clang-format.sh``
65 and for the pre-commit hook, you also need to run this in each of your |Gromacs| repositories::
66
67   git config hooks.clangformatpath /path/to/clang-format
68
69 Alternatively, if you just want to use ``clang-format.sh``, you can set the
70 ``CLANG_FORMAT`` environment variable to ``/path/to/clang-format``.
71
72 As above, see the sections below for using the pre-commit hook or git filters.
73
74 What is automatically formatted?
75 --------------------------------
76
77 To identify which files are subject to automatic formatting, the scripts use
78 git filters, specified in ``.gitattributes`` files.  Only files that have the
79 attribute ``filter`` set to one of the below values are processed:
80
81 - ``filter=complete_formatting``: Performs all formatting. Uses clang-format for code formatting.
82 - ``filter=uncrustify``: uncrustify is run. Deprecated and here for historical reasons.
83 - ``filter=clangformat``: clang-format is run.
84 - ``filter=includesort``: include order is enforced and copyright headers are checked.
85 - ``filter=copyright``: only copyright headers are checked.
86
87 Other files are ignored by ``uncrustify.sh``, ``clang-format.sh``,
88 ``copyright.sh`` and ``reformat_all.sh`` scripts (see below).
89
90
91 Scripts
92 -------
93
94 ``copyright.py``
95 ^^^^^^^^^^^^^^^^
96
97 This script provides low-level functionality to check and update copyright
98 headers in C/C++ source files, as well as in several other types of files like
99 CMake and Python scripts.
100
101 This file is also used as a loadable Python module for kernel generators, and
102 provides the functionality to generate conformant copyright headers for such
103 scripts.
104
105 The script is similar to uncrustify in that there is rarely need to run it
106 directly, but instead the bash scripts below use it internally.  You can run
107 the script with ``--help`` option if you want to see what all options it provides
108 if you need to do some maintenance on the copyright headers themselves.
109
110 ``uncrustify.sh``
111 ^^^^^^^^^^^^^^^^^
112
113 The information for ``uncrustify`` is mainly provided for historical reasons,
114 as the actual code formatting is now done using ``clang-format``.
115
116 This script runs ``uncrustify`` on modified files and reports/applies the results.
117 By default, the current HEAD commit is compared to the work tree,
118 and files that
119
120 1. are different between these two trees and
121 2. change under uncrustify
122
123 are reported.  This behavior can be changed by
124
125 1. Specifying an ``--rev=REV`` argument, which uses ``REV`` instead of HEAD as
126    the base of the comparison.  A typical use case is to specify ``--rev=HEAD^``
127    to check the HEAD commit.
128 2. Specifying an action:
129
130    - ``check-*``:   reports the files that uncrustify changes
131    - ``diff-*``:    prints the actual diff of what would change
132    - ``update-*``:  applies the changes to the repository
133    - ``*-workdir``: operates on the working directory (files on disk)
134    - ``*-index``:   operates on the index of the repository
135
136    For convenience, if you omit the workdir/index suffix, workdir is assumed
137    (i.e., ``diff`` equals ``diff-workdir``).
138 3. Specifying ``--uncrustify=off``, which does not run uncrustify.
139
140 By default, ``update-*`` refuses to update dirty files (i.e., that differ
141 between the disk and the index) to make it easy to revert the changes.
142 This can be overridden by adding a ``-f``/``--force`` option.
143
144 ``copyright.sh``
145 ^^^^^^^^^^^^^^^^
146
147 This script runs ``copyright.py`` on modified files and reports/applies the results.
148 By default, the current HEAD commit is compared to the work tree,
149 and files that
150
151 1. are different between these two trees and
152 2. change under have outdated copyright header
153
154 are reported.  This behavior can be changed by
155
156 1. Specifying an ``--rev=REV`` argument, which uses ``REV`` instead of HEAD as
157    the base of the comparison.  A typical use case is to specify ``--rev=HEAD^``
158    to check the HEAD commit.
159 2. Specifying ``--copyright=<mode>``, which alters the level of copyright
160    checking is done:
161
162    ``off``
163      does not check copyright headers at all
164    ``year``
165      only update copyright year in new-format copyright headers
166    ``add``
167      in addition to ``year``, add copyright headers to files that do not
168      have any
169    ``update``
170      in addition to ``year`` and ``add``, also update new-format copyright
171      headers if they are broken or outdated
172    ``replace``
173      replace any copyright header with a new-format copyright header
174    ``full``
175      do all of the above
176
177 By default, ``update-*`` refuses to update dirty files (i.e., that differ
178 between the disk and the index) to make it easy to revert the changes.
179 This can be overridden by adding a ``-f``/``--force`` option.
180
181 ``clang-format.sh``
182 ^^^^^^^^^^^^^^^^^^^
183
184 This script runs ``clang-format`` on modified files and reports/applies the results.
185 By default, the current HEAD commit is compared to the work tree,
186 and files that
187
188 1. are different between these two trees and
189 2. change under clang-format
190
191 are reported.  This behavior can be changed by
192
193 1. Specifying an ``--rev=REV`` argument, which uses ``REV`` instead of HEAD as
194    the base of the comparison.  A typical use case is to specify ``--rev=HEAD^``
195    to check the HEAD commit.
196 2. Specifying an action:
197
198    - ``check-*``:   reports the files that uncrustify changes
199    - ``diff-*``:    prints the actual diff of what would change
200    - ``update-*``:  applies the changes to the repository
201    - ``*-workdir``: operates on the working directory (files on disk)
202    - ``*-index``:   operates on the index of the repository
203
204    For convenience, if you omit the workdir/index suffix, workdir is assumed
205    (i.e., ``diff`` equals ``diff-workdir``).
206 3. Specifying ``--format=off``, which does not run clang-format.
207
208 By default, ``update-*`` refuses to update dirty files (i.e., that differ
209 between the disk and the index) to make it easy to revert the changes.
210 This can be overridden by adding a ``-f``/``--force`` option.
211
212 git pre-commit hook
213 ^^^^^^^^^^^^^^^^^^^
214
215 If you want to run ``uncrustify.sh``, ``copyright.sh`` and/or
216 ``clang-format.sh`` automatically for changes you make, you can
217 configure a pre-commit hook using ``admin/git-pre-commit``:
218
219 1. Copy the ``git-pre-commit`` script to .git/hooks/pre-commit.
220 2. Specify the path to uncrustify for the hook if you have not already done
221    so::
222
223      git config hooks.uncrustifypath /path/to/uncrustify
224
225 3. Set the operation mode for the hook::
226
227      git config hooks.uncrustifymode check
228      git config hooks.copyrightmode  update
229
230 For ``clang-format``, follow these steps instead:
231
232 1. Specify the path to ``clang-format`` for the hook if you have not already done
233    so::
234
235      git config hooks.clangformatpath /path/to/clang-format
236
237 2. Set the operation mode for the hook::
238
239      git config hooks.clangformatmode check
240
241 With this configuration, all source files modified in the commit are run
242 through the respective code formatting tool and checked for correct copyright headers.
243 If any file would be changed by ``uncrustify.sh``, ``clang-format.sh`` or ``copyright.sh``,
244 the names of those files are reported and the commit is prevented.
245 The issues can be fixed by running the scripts manually.
246
247 To disable the hook without removing the ``pre-commit`` file, you can set ::
248
249   git config hooks.uncrustifymode off
250   git config hooks.copyrightmode off
251   git config hooks.clangformatmode off
252
253 To disable it temporarily for a commit, set NO_FORMAT_CHECK environment
254 variable.  For example, ::
255
256     NO_FORMAT_CHECK=1 git commit -a
257
258 You can also run ``git commit --no-verify``, but that also disables other hooks,
259 such as the Change-Id ``commit-msg`` hook used by Gerrit.
260
261 Note that when you run ``git commit --amend``, the hook is only run for the
262 changes that are getting amended, not for the whole commit.  During a rebase,
263 the hook is not run.
264
265 The actual work is done by the ``admin/uncrustify.sh``, ``admin/clang-format.sh``
266 and ``admin/copyright.sh`` scripts, which get run with the ``check-index`` action,
267 and with ``--uncrustify``, ``--copyright`` and ``--format`` getting set according
268 to the ``git config`` settings.
269
270 ``reformat_all.sh``
271 ^^^^^^^^^^^^^^^^^^^
272
273 This script runs uncrustify, clang-format, ``copyright.py``, or the include sorter for all
274 applicable files in the source tree.  See ``reformat_all.sh -h`` for the
275 invocation.
276
277 The script can also produce the list of files for which these commands would be
278 run.  To do this, specify ``list-files`` on the command line and use
279 ``--filter=<type>`` to specify which command to get the file list for.  This can
280 be used together with, e.g., ``xargs`` to run other scripts on the same set of
281 files.
282
283 For all the operations, it is also possible to apply patters (of the same style
284 that various git commands accept, i.e., ``src/*.cpp`` matches all ``.cpp`` files
285 recursively under ``src/``).  The patterns can be specified with
286 ``--pattern=<pattern>``, and multiple ``--pattern`` arguments can be given.
287
288 As with ``uncrustify.sh``, ``-f``/``--force`` is necessary if the working tree and
289 the git index do not match.
290
291
292 Using git filters
293 -----------------
294
295 An alternative to using a pre-commit hook to automatically apply uncrustify or
296 clang-format on changes is to use a git filter (does not require either of the scripts,
297 only the ``.gitattributes`` file).  You can run ::
298
299   git config filter.complete_formatting.clean \
300       "/path/to/uncrustify -c admin/uncrustify.cfg -q -l cpp"
301   git config filter.clangformat.clean \
302       "/path/to/clang-format -i"
303
304 To configure a filter for all files that specify ``filter=complete_formatting`` attribute
305 that indicates that all formatting steps should be performed.
306
307 The pre-commit hook + manually running the scripts gives better/more
308 intuitive control (with the filter, it is possible to have a work tree that is
309 different from HEAD and still have an empty ``git diff``) and provides better
310 performance for changes that modify many files.  It is the only way that
311 currently also checks the copyright headers.
312
313 The filter allows one to transparently merge branches that have not been run
314 through the source checkers, and is applied more consistently (the pre-commit hook is
315 not run for every commit, e.g., during a rebase).