Convert developer manual to rst
[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.
89   * All source files must include "gmxpre.h" as the first header.
90   * A source/header file should include "config.h" if and only if it uses a
91     macro declared there.
92   * If the file has a git attribute to identify it as a candidate for include
93     sorting, the include sorter described below should not produce any
94     changes (i.e., the file should follow :doc:`includestyle`).
95
96 * For documented files:
97
98   * Installed headers should have public documentation, and other files should
99     not.
100   * The API level specified for a file should not be higher than where its
101     documentation is visible.  For example, only publicly documented headers
102     should be specified as part of the public API.
103   * If an ``\ingroup module_foo`` exists, it should match the subdirectory
104     that the file is actually part of in the file system.
105   * If a ``\defgroup module_foo`` exists for the subdirectory where the file
106     is, the file should contain ``\ingroup module_foo``.
107   * Files should not include other files whose documentation visibility is
108     lower (if the included file is not documented, the check is skipped).
109
110 * For files that are part of documented modules
111   (``\defgroup module_foo`` exists for the subdirectory), or are explicitly
112   documented to be internal or in the library API:
113
114   * Such files should not be included from outside their module if they are
115     undocumented (for documented modules) or are not specified as part of
116     library or public API.
117
118 * For all modules:
119
120   * There should not be cyclic include dependencies between modules.
121
122 As a side effect, the XML extraction makes Doxygen parse all comments in the
123 code, even if they do not appear in the documentation.  This can reveal latent
124 issues in the comments, like invalid Doxygen syntax.  The messages from the XML
125 parsing are stored in ``docs/doxygen/doxygen-xml.log`` in the build tree, similar to
126 other Doxygen runs.
127
128 Suppressing issues
129 ^^^^^^^^^^^^^^^^^^
130
131 The script is not currently perfect (either because of unfinished
132 implementation, or because Doxygen bugs or incompleteness of the Doxygen XML
133 output), and the current code also contains issues that the script detects, but
134 the authors have not fixed.  To allow the script to still be used,
135 ``doxygen/suppressions.txt`` contains a list of issues that are filtered out from
136 the report.  The syntax is simple::
137
138     <file>: <text>
139
140 where ``<file>`` is a path to the file that reports the message, and ``<text>`` is
141 the text reported.  Both support ``*`` as a wildcard.  If ``<file>`` is empty, the
142 suppression matches only messages that do not have an associated file.
143 ``<file>`` is matched against the trailing portion of the file name to make it
144 work even though the script reports absolute paths.
145 Empty lines and lines starting with ``#`` are ignored.
146
147 To add a suppression for an issue, the line that reports the issue can be
148 copied into ``suppressions.txt``, and the line number (if any) removed.  If the
149 issue does not have a file name (or a pseudo-file) associated, a leading ``:``
150 must be added.  To cover many similar issues, parts of the line can then be
151 replaced with wildcards.
152
153 A separate suppression mechanism is in place for cyclic dependencies: to
154 suppress a cycle between moduleA and moduleB, add a line with format ::
155
156     moduleA -> moduleB
157
158 into ``doxygen/cycle-suppressions.txt``.  This suppresses all cycles that contain
159 the mentioned edge.  Since a cycle contains multiple edges, the suppression
160 should be made for the edge that is determined to be an incorrect dependency.
161 This also affects the layout of the include dependency graphs (see below): the
162 suppressed edge is not considered when determining the dependency order, and is
163 shown as invalid in the graph.
164
165 .. _dev-include-sorter:
166
167 Include order sorting
168 ---------------------
169
170 The script checks include ordering according to :doc:`includestyle`.
171 If it is not obvious how the includes should be changed to make the script
172 happy, or bulk changes are needed in multiple files, e.g., because of a header
173 rename or making a previously public header private, it is possible to run a
174 Python script that does the sorting::
175
176     docs/doxygen/includesorter.py -S . -B ../build <files>
177
178 The script needs to know the location of the source tree (given with ``-S``) and
179 the build tree (given with ``-B``), and sorts the given files.  To sort the whole
180 source tree, one can also use::
181
182     admin/reformat_all.sh includesort -B=../build
183
184 For the sorter to work correctly, the build tree should contain up-to-date list
185 of installed files and Doxygen XML documentation.  The former is created
186 automatically when ``cmake`` is run, and the latter can be built using the
187 ``doxygen-xml`` target.
188
189 Note that currently, the sorter script does not change between angle brackets
190 and quotes in include statements.
191
192 Include dependency graphs
193 -------------------------
194
195 The same set of Python scripts can also produce include dependency graphs with
196 some additional annotations compared to what, e.g., Doxygen produces for a
197 directory dependency graph.  Currently, a module-level graph is automatically
198 built when the Doxygen documentation is built and embedded in the documentation
199 (not in the public API documentation).  The graph, together with a legend, is
200 on a separate page: `Module dependency graph`__
201
202 __ doxygen-page-modulegraph_
203
204 The Python script produces the graphs in a format suitable for ``dot`` (from the
205 ``graphviz`` package) to lay them out.  The build system also provides a
206 ``dep-graphs`` target that generates PNG files from the intermediate ``dot`` files.
207 In addition to the module-level graph, a file-level graph is produced for
208 each module, showing the include dependencies within that module.
209 The file-level graphs can only be viewed as the PNG files, with some
210 explanation of the notation below.  Currently, these are mostly for eye candy,
211 but they can also be used for analyzing problematic dependencies to clean up
212 the architecture.
213
214 Both the intermediate ``.dot`` files and the final PNG files are put under
215 ``docs/doxygen/depgraphs/`` in the build tree.
216
217 File graphs
218 ^^^^^^^^^^^
219
220 The graphs are written to :file:`{module_name}-deps.dot.png`.
221
222 Node colors:
223
224 light blue
225   public API (installed) headers
226 dark blue
227   library API headers
228 gray
229   source files
230 light green
231   test files
232 white
233   other files
234
235 Each edge signifies an include dependency; there is no additional information
236 currently included.
237
238 .. include:: doxygen-links.rst