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