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