41f5cca3927fe87a7a8dd2eb7c51dca027253582
[alexxy/gromacs.git] / docs / dev-manual / gmxtree.md
1 Source tree checker scripts {#page_dev_gmxtree}
2 ===========================
3
4 There is a set of Python scripts, currently under `docs/doxygen/`, that check
5 various aspects of the source tree for consistency.  The script is based on
6 producing an abstract representation of the source tree from various sources:
7  * List of files in the source tree (for overall layout of the source tree)
8  * List of installed headers (extracted from the generated build system)
9  * git attributes (to limit the scope of some checks)
10  * Doxygen XML documentation:
11    * For tags about public/private nature of documented headers and other
12      constructs
13    * For actual documented constructs, to check them for consistency
14  * Hard-coded knowledge about the \Gromacs source tree layout
15
16 This representation is then used for various purposes:
17  * Checking Doxygen documentation elements for common mistakes: missing brief
18    descriptions, mismatches in file and class visibility, etc.
19  * Checking for consistent usage and documentation of headers: e.g., a header
20    that is documented as internal to a module should not be used outside that
21    module.
22  * Checking for module-level cyclic dependencies
23  * Checking for consistent style and order of \#include directives
24    (see \ref page_devstyle_includes)
25  * Actually sorting and reformatting \#include directives to adhere to the
26    checked style
27  * Generating dependency graphs between modules and for files within modules
28
29 The checks are run as part of a single `check-source` target, but are described
30 in separate sections below.  In addition to printing the issues to `stderr`,
31 the script also writes them into `docs/doxygen/check-source.log` for later
32 inspection.  Jenkins runs the checks as part of the Documentation job, and the
33 build is marked unstable if any issues are found.
34
35 For correct functionality, the scripts depend on correct usage of Doxygen
36 annotations described in \ref page_doxygen, in particular the visibility and
37 API definitions in file-level comments.
38
39 For some false positives from the script, the suppression mechanism described
40 below is the easiest way to silence the script, but otherwise the goal would be
41 to minimize the number of suppressions.
42
43 The scripts require Python 2.7 (other versions may work, but have not been
44 tested).
45
46 To understand how the scripts work internally, see comments in the Python
47 source files under `docs/doxygen/`.
48
49 Checker details
50 ===============
51
52 The `check-source` target currently checks for a few different types of issues.
53 These are listed in detail below, mainly related to documentation and include
54 dependencies.  Note in particular that the include dependency checks are much
55 stricter for code in modules/directories that are documented with a
56 \c \\defgroup: all undocumented code is assumed to be internal to such modules.
57 The rationale is that such code has gotten some more attention, and some effort
58 should also have been put into defining what is the external interface of the
59 module and documenting it.
60
61 * For all Doxygen documentation (currently does not apply for members that do
62   not appear in the documentation):
63    * If a member has documentation, it should have a brief description.
64    * A note is issued for in-body documentation for functions, since this is
65      ignored by our current settings.
66    * If a class has documentation, it should have public documentation only if
67      it appears in an installed header.
68    * If a class and its containing file has documentation, the class
69      documentation should not be visible if the file documentation is not.
70 * For all files:
71    * Consistent usage of
72
73          #include "..." // This should be used for Gromacs headers
74
75      and
76
77          #include <...> // This should be used for system and external headers
78
79    * Installed headers must not include non-installed headers.
80    * All source files must include "gmxpre.h" as the first header.
81    * A source/header file should include "config.h" if and only if it uses a
82      macro declared there.
83    * If the file has a git attribute to identify it as a candidate for include
84      sorting, the include sorter described below should not produce any
85      changes (i.e., the file should follow \ref page_devstyle_includes).
86 * For documented files:
87    * Installed headers should have public documentation, and other files should
88      not.
89    * The API level specified for a file should not be higher than where its
90      documentation is visible.  For example, only publicly documented headers
91      should be specified as part of the public API.
92    * If an \c \\ingroup `module_foo` exists, it should match the subdirectory
93      that the file is actually part of in the file system.
94    * If a \c \\defgroup `module_foo` exists for the subdirectory where the file
95      is, the file should contain \c \\ingroup `module_foo`.
96    * Files should not include other files whose documentation visibility is
97      lower (if the included file is not documented, the check is skipped).
98 * For files that are part of documented modules
99   (\c \\defgroup `module_foo` exists for the subdirectory), or are explicitly
100   documented to be internal or in the library API:
101    * Such files should not be included from outside their module if they are
102      undocumented (for documented modules) or are not specified as part of
103      library or public API.
104 * For all modules:
105    * There should not be cyclic include dependencies between modules.
106
107 As a side effect, the XML extraction makes Doxygen parse all comments in the
108 code, even if they do not appear in the documentation.  This can reveal latent
109 issues in the comments, like invalid Doxygen syntax.  The messages from the XML
110 parsing are stored in `docs/doxygen/doxygen-xml.log` in the build tree, similar to
111 other Doxygen runs.
112
113 Suppressing issues
114 ------------------
115
116 The script is not currently perfect (either because of unfinished
117 implementation, or because Doxygen bugs or incompleteness of the Doxygen XML
118 output), and the current code also contains issues that the script detects, but
119 the authors have not fixed.  To allow the script to still be used,
120 `doxygen/suppressions.txt` contains a list of issues that are filtered out from
121 the report.  The syntax is simple:
122
123     <file>: <text>
124
125 where `<file>` is a path to the file that reports the message, and `<text>` is
126 the text reported.  Both support `*` as a wildcard.  If `<file>` is empty, the
127 suppression matches only messages that do not have an associated file.
128 `<file>` is matched against the trailing portion of the file name to make it
129 work even though the script reports absolute paths.
130 Empty lines and lines starting with `#` are ignored.
131
132 To add a suppression for an issue, the line that reports the issue can be
133 copied into `suppressions.txt`, and the line number (if any) removed.  If the
134 issue does not have a file name (or a pseudo-file) associated, a leading `:`
135 must be added.  To cover many similar issues, parts of the line can then be
136 replaced with wildcards.
137
138 A separate suppression mechanism is in place for cyclic dependencies: to
139 suppress a cycle between moduleA and moduleB, add a line with format
140
141     moduleA -> moduleB
142
143 into `doxygen/cycle-suppressions.txt`.  This suppresses all cycles that contain
144 the mentioned edge.  Since a cycle contains multiple edges, the suppression
145 should be made for the edge that is determined to be an incorrect dependency.
146 This also affects the layout of the include dependency graphs (see below): the
147 suppressed edge is not considered when determining the dependency order, and is
148 shown as invalid in the graph.
149
150 Include order sorting {#section_dev_includesorter}
151 =====================
152
153 The script checks include ordering according to \ref page_devstyle_includes.
154 If it is not obvious how the includes should be changed to make the script
155 happy, or bulk changes are needed in multiple files, e.g., because of a header
156 rename or making a previously public header private, it is possible to run a
157 Python script that does the sorting:
158
159     docs/doxygen/includesorter.py -S . -B ../build <files>
160
161 The script needs to know the location of the source tree (given with `-S`) and
162 the build tree (given with `-B`), and sorts the given files.  To sort the whole
163 source tree, one can also use:
164
165     admin/reformat_all.sh includesort -B=../build
166
167 For the sorter to work correctly, the build tree should contain up-to-date list
168 of installed files and Doxygen XML documentation.  The former is created
169 automatically when `cmake` is run, and the latter can be built using the
170 `doxygen-xml` target.
171
172 Note that currently, the sorter script does not change between angle brackets
173 and quotes in include statements.
174
175 Include dependency graphs
176 =========================
177
178 The same set of Python scripts can also produce include dependency graphs with
179 some additional annotations compared to what, e.g., Doxygen produces for a
180 directory dependency graph.  Currently, a module-level graph is automatically
181 built when the Doxygen documentation is built and embedded in the documentation
182 (not in the public API documentation).  The graph, together with a legend, is
183 on a separate page: \ref page_modulegraph.
184
185 The Python script produces the graphs in a format suitable for `dot` (from the
186 `graphviz` package) to lay them out.  The build system also provides a
187 `dep-graphs` target that generates PNG files from the intermediate `dot` files.
188 In addition to the module-level graph, a file-level graph is produced for
189 each module, showing the include dependencies within that module.
190 The file-level graphs can only be viewed as the PNG files, with some
191 explanation of the notation below.  Currently, these are mostly for eye candy,
192 but they can also be used for analyzing problematic dependencies to clean up
193 the architecture.
194
195 Both the intermediate `.dot` files and the final PNG files are put under
196 `docs/doxygen/depgraphs/` in the build tree.
197
198 File graphs
199 -----------
200
201 The graphs are written to <em>module_name</em>`-deps.dot.png`.
202
203 Node colors:
204 <dl>
205 <dt>light blue</dt>
206 <dd>public API (installed) headers</dd>
207 <dt>dark blue</dt>
208 <dd>library API headers</dd>
209 <dt>gray</dt>
210 <dd>source files</dd>
211 <dt>light green</dt>
212 <dd>test files</dd>
213 <dt>white</dt>
214 <dd>other files</dd>
215 </dl>
216
217 Each edge signifies an include dependency; there is no additional information
218 currently included.