5461b564beb32fab17398e5903bce1b15b3dfdd3
[alexxy/gromacs.git] / docs / dev-manual / uncrustify.md
1 Automatic source code formatting {#page_dev_uncrustify}
2 ================================
3
4 The source code can be automatically formatted using uncrustify, an automatic
5 source code formatting tool, to follow the guidelines in
6 \ref page_devstyle_formatting.
7 Additionally, Python scripts are used for a few other automatic
8 formatting/checking tasks.  The overview tools page contains a list of these
9 tools: \ref section_dev_formattingtools.
10 This page provides more details for uncrustify and copyright scripts.
11
12 Jenkins uses these same scripts (in particular, `uncrustify.sh` and the
13 `check-source` target) to enforce that the code stays invariant under such
14 formatting.
15
16 Setting up uncrustify
17 =====================
18
19 A patched version of uncrustify is used for \Gromacs.  To set this up, you need
20 to do these (once):
21  1. Change to a directory under which you want to build uncrustify and run:
22
23         git clone -b gromacs git://github.com/rolandschulz/uncrustify.git
24         cd uncrustify
25         ./configure
26         make
27
28  2. Copy the binary `src/uncrustify` into a directory of your choice
29     (`/path/to/uncrustify` below).
30
31 Alternatively, if you are running Linux, you can try whether the binary from
32 <http://redmine.gromacs.org/issues/845> works for you.
33
34 In order to use the binary for `uncrustify.sh` and for the pre-commit hook, you
35 also need to run this in each of your \Gromacs repositories:
36
37     git config hooks.uncrustifypath /path/to/uncrustify
38
39 Alternatively, if you just want to use `uncrustify.sh`, you can set the
40 UNCRUSTIFY environment variable to `/path/to/uncrustify`.
41
42 Using the pre-commit hook or git filters needs additional setup; see the
43 respective sections below.
44
45 What is automatically formatted?
46 ================================
47
48 To identify which files are subject to automatic formatting, the scripts use
49 git filters, specified in `.gitattributes` files.  Only files that have the
50 attribute `filter` set to one of the below values are processed:
51  - `filter=uncrustify`: uncrustify is run, copyright headers are checked, and
52    include order is enforced
53  - `filter=uncrustify_only`: only uncrustify is run
54  - `filter=includesort`: include order is enforced and copyright headers are
55    checked
56  - `filter=copyright`: only copyright headers are checked
57 Other files are ignored by `uncrustify.sh` and `reformat_all.sh` scripts (see
58 below).
59
60
61 Scripts
62 =======
63
64 `copyright.py`
65 --------------
66
67 This script provides low-level functionality to check and update copyright
68 headers in C/C++ source files, as well as in several other types of files like
69 CMake and Python scripts.
70
71 This file is also used as a loadable Python module for kernel generators, and
72 provides the functionality to generate conformant copyright headers for such
73 scripts.
74
75 The script is similar to uncrustify in that there is rarely need to run it
76 directly, but instead the bash scripts below use it internally.  You can run
77 the script with `--help` option if you want to see what all options it provides
78 if you need to do some maintenance on the copyright headers themselves.
79
80 `uncrustify.sh`
81 ---------------
82
83 This script runs uncrustify and `copyright.py` on modified files and
84 reports/applies the results.
85 By default, the current HEAD commit is compared to the work tree,
86 and files that
87
88  1. are different between these two trees and
89  2. change under uncrustify and/or have outdated copyright header
90
91 are reported.  This behavior can be changed by
92
93  1. Specifying an `--rev=REV` argument, which uses `REV` instead of HEAD as
94     the base of the comparison.  A typical use case is to specify `--rev=HEAD^`
95     to check the HEAD commit.
96  2. Specifying an action:
97       - `check-*`:   reports the files that uncrustify changes
98       - `diff-*`:    prints the actual diff of what would change
99       - `update-*`:  applies the changes to the repository
100       - `*-workdir`: operates on the working directory (files on disk)
101       - `*-index`:   operates on the index of the repository
102     For convenience, if you omit the workdir/index suffix, workdir is assumed
103     (i.e., `diff` equals `diff-workdir`).
104  3. Specifying `--uncrustify=off`, which does not run uncrustify.
105  4. Specifying `--copyright=<mode>`, which alters the level of copyright
106     checking is done:
107       - `off`:     does not check copyright headers at all
108       - `year`:    only update copyright year in new-format copyright headers
109       - `add`:     in addition to 'year', add copyright headers to files that
110                    do not have any
111       - `update`:  in addition to 'year' and 'add', also update new-format
112                    copyright headers if they are broken or outdated.
113       - `replace`: replace any copyright header with a new-format copyright
114                    header
115       - `full`:    do all of the above
116
117 By default, `update-*` refuses to update dirty files (i.e., that differ
118 between the disk and the index) to make it easy to revert the changes.
119 This can be overridden by adding a `-f`/`--force` option.
120
121 git pre-commit hook
122 -------------------
123
124 If you want to run `uncrustify.sh` automatically for changes you make, you can
125 configure a pre-commit hook using `admin/git-pre-commit`:
126  1. Copy the `git-pre-commit` script to .git/hooks/pre-commit.
127  2. Specify the path to uncrustify for the hook if you have not already done
128     so:
129         git config hooks.uncrustifypath /path/to/uncrustify
130  3. Set the operation mode for the hook:
131         git config hooks.uncrustifymode check
132         git config hooks.copyrightmode  update
133
134 With this configuration, all source files modified in the commit are run
135 through uncrustify and checked for correct copyright headers.
136 If any file would be changed by `uncrustify.sh`, the names of those files are
137 reported and the commit is prevented.  The issues can be fixed by running
138 `uncrustify.sh` manually.
139
140 To disable the hook without removing the `pre-commit` file, you can set
141
142     git config hooks.uncrustifymode off
143     git config hooks.copyrightmode off
144
145 To disable it temporarily for a commit, set NO_FORMAT_CHECK environment
146 variable.  For example,
147
148     NO_FORMAT_CHECK=1 git commit -a
149
150 You can also run `git commit --no-verify`, but that also disables other hooks,
151 such as the Change-Id commit-msg hook used by Gerrit.
152
153 Note that when you run `git commit --amend`, the hook is only run for the
154 changes that are getting amended, not for the whole commit.  During a rebase,
155 the hook is not run.
156
157 The actual work is done by the admin/uncrustify.sh script, which gets
158 run with the 'check-index' action, and with `--uncrustify` and `--copyright`
159 getting set according to the `git config` settings.
160
161 `reformat_all.sh`
162 -----------------
163
164 This script runs uncrustify, `copyright.py`, or the include sorter for all
165 applicable files in the source tree.  See `reformat_all.sh -h` for the
166 invocation.
167
168 The script can also produce the list of files for which these commands would be
169 run.  To do this, specify `list-files` on the command line and use
170 `--filter=<type>` to specify which command to get the file list for.  This can
171 be used together with, e.g., `xargs` to run other scripts on the same set of
172 files.
173
174 For all the operations, it is also possible to apply patters (of the same style
175 that various git commands accept, i.e., `src/*.cpp` matches all `.cpp` files
176 recursively under `src/`).  The patterns can be specified with
177 `--pattern=<pattern>`, and multiple `--pattern` arguments can be given.
178
179 As with `uncrustify.sh`, `-f`/`--force` is necessary if the working tree and
180 the git index do not match.
181
182
183 Using git filters
184 =================
185
186 An alternative to using a pre-commit hook to automatically apply uncrustify on
187 changes is to use a git filter (does not require `uncrustify.sh`, only the
188 `.gitattributes` file).  You can run
189
190     git config filter.uncrustify.clean \
191         "/path/to/uncrustify -c admin/uncrustify.cfg -q -l cpp"
192
193 To configure a filter for all files that specify `filter=uncrustify` attribute.
194
195 The pre-commit hook + manually running `uncrustify.sh` gives better/more
196 intuitive control (with the filter, it is possible to have a work tree that is
197 different from HEAD and still have an empty `git diff`) and provides better
198 performance for changes that modify many files.  It is the only way that
199 currently also checks the copyright headers.
200
201 The filter allows one to transparently merge branches that have not been run
202 through uncrustify, and is applied more consistently (the pre-commit hook is
203 not run for every commit, e.g., during a rebase).