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