Fortran Autodoc
sphinxfortran_ng provides an autodoc-style extension for Fortran source code. It automatically extracts documentation from Fortran files and generates reStructuredText output describing modules, routines, variables, and derived types.
The design and usage closely follow sphinx.ext.autodoc for Python. The
comment conventions that the sources must follow are described in
Formatting Fortran (.f90) Code for Auto-Documentation.
Enabling the Extension
Add the Fortran domain and autodoc extensions to your conf.py. Both
are required: the domain creates the f: domain and the autodoc extension
adds the f:auto* directives to it.
extensions += [
"sphinxfortran_ng.fortran_domain",
"sphinxfortran_ng.fortran_autodoc",
]
Configure the Fortran source search path:
fortran_src = ["../src"]
fortran_ext = ["f90", "F90", "f95", "F95"]
The sources are parsed once, when the builder is initialised
(fortran_parse()). Sphinx logs
parsing fortran sources... done, or no fortran files found when
nothing matches, in which case every f:auto* directive silently produces
nothing.
Configuration values
Name |
Default |
Meaning |
|---|---|---|
|
|
List (or a single string) of files, glob patterns and directories.
Directories are scanned for |
|
|
Extensions looked for in the directories of |
|
|
Indentation used in the generated reST: a number of spaces, |
|
|
Underline character of the titles generated in |
|
|
Accepted for compatibility. It is currently not used: files are opened with the default encoding of Python. |
|
|
Registered, but currently not read: the subsection type is set by
the |
The autodoc extension also registers the object types ftype and fvar
(:ftype:, :fvar:) which belong to the generic Sphinx object mechanism
and are independent of the f: domain.
Directives at a glance
Directive |
Documents |
|---|---|
|
A whole module: description, quick access, used modules, types, variables, routines. |
|
Only the variables of a module (same options as |
|
One function, subroutine or generic interface. |
|
One function / subroutine. |
|
See the caveat in Known limitations; prefer |
|
One derived type, with its components. |
|
One module variable. |
|
One main program. |
|
Everything found in one source file. |
Every argument is a name in lower case (the parser lower-cases the
names of the source). For the object directives the name of the module may
prefix it, separated by /, and is ignored: mymodule/solve is the same
as solve.
.. f:automodule::
Document a Fortran module and optionally its contents.
The f:automodule directive takes a module found in the sources parsed at
start-up and generates documentation for the module itself and for the
entities it contains.
Syntax
.. f:automodule:: module_name
:members: name1, name2
:undoc-members: name3
:forceadd-members: name4
:include-private:
:title_underline: -
:subsection_type: rubric
:indent: tab
:hide-output: 1
Options
All options are optional, and every option takes effect only for this directive: the previous configuration is restored at the end.
:members:Comma separated list of names. When it is given, only the listed variables, types and routines of the module are documented (a private entity is documented if it is explicitly listed). Without a value all the public members are documented.
:undoc-members:Comma separated list of names of members to leave out.
Note
Despite its name, and unlike the Python
:undoc-members:, this option does not switch the display of undocumented members on: those are always shown. It is the way to hide chosen members, for instance the internal variables ending in_ofED_INPUT_VARS.Do not combine it with
:members:: when:undoc-members:is given, it is applied instead of the restriction of:members:.:forceadd-members:Comma separated list of names that are documented whatever their visibility and the other options. This is the way to document a member declared
privatein the module.:include-private:Intended to include the
privatemembers.Warning
In the current version this option has no effect: a bare option is read as an empty string, which is ignored, and any value given is stored as a non-
Nonestring, which still excludes the private members. Use:forceadd-members:or:members:with explicit names instead. From Python, settingF90toRst.exclude_private = Nonedoes include them.:title_underline:Character used to underline the titles, when
:subsection_type:istitle. Typical values are-,~or^. Ignored inrubricmode.:subsection_type:Control how the parts of a module (Description, Quick access, Types, Variables, Subroutines and functions, …) are introduced.
rubric(default) Each part is introduced by a
.. rubric::and does not appear in the table of contents.titleEach part is a real section, underlined with
:title_underline:. It then shows in the table of contents. The underline must be consistent with the heading hierarchy of the page that contains the directive.
Any other value,
sectionincluded, behaves likerubric.:indent:Indentation of the generated text. Only
tabandspaceare understood; a number given here is not converted to spaces and would be used as the text of the indentation. Set the number of spaces once for all withfortran_indentinconf.py.:hide-output:Only declare the module (
f:module) and produce none of its contents. The option must be given a value, for instance:hide-output: 1, since an empty value is ignored. This is useful to register the module in the index and for cross references while the content is written by hand.
Generated layout
The parts of a module, in this order, are: the f:module declaration (with
the synopsis); Description; Quick access (the lists of types, variables
and routines); Used modules and External modules; Types; Variables;
Subroutines and functions. A part that is empty is omitted. For
SF_ARRAYS the head is:
.. f:module:: sf_arrays
:synopsis: SciFortran module for array creation and manipulation
.. rubric:: Description
SciFortran module for array creation and manipulation
.. rubric:: Quick access
:Routines: :f:func:`arange`, :f:func:`linspace`, :f:func:`logspace`, :f:func:`powspace`, :f:func:`upminterval`, :f:func:`upmspace`
With :subsection_type: title and :title_underline: - the same parts of
a small module become sections:
.. f:module:: m
:synopsis: Tiny module used to show the layout.
Description
-----------
Tiny module used to show the layout.
Quick access
------------
:Variables: :f:var:`pi`
:Routines: :f:func:`hello`
Variables
---------
.. f:variable:: pi
Circle constant
:Type: real
Subroutines and functions
-------------------------
.. f:subroutine:: hello()
Says hello.
and :hide-output: 1 reduces the output to:
.. f:module:: m
:synopsis: Tiny module used to show the layout.
Example
Array creation
==============
.. f:automodule:: sf_arrays
:subsection_type: title
:title_underline: -
Document only two routines of a larger module:
.. f:automodule:: ed_input_vars
:members: ed_read_input, ed_update_input
Document a module without its internal helper variables (the ones ending in
_ in ED_INPUT_VARS):
.. f:automodule:: ed_input_vars
:undoc-members: ed_twin_, ed_total_ud_, uloc_, pair_field_
.. f:automodvars::
Document only the variables of a module. It accepts the same options as
f:automodule (so :members: and :undoc-members: work) but writes
neither a module declaration nor any title: the output is the list of the
variables followed by their descriptions, to be placed under a heading of
your own.
Input variables
---------------
.. f:automodvars:: ed_input_vars
For a small module the output is:
:f:var:`pi`
.. f:variable:: pi
Circle constant
:Type: real
Note
The variables are only registered under the module if an f:module
directive, or an f:automodule with :hide-output: 1, has been
written before.
.. f:autoroutine::
Document a single Fortran subroutine, function or generic interface.
Syntax
.. f:autoroutine:: routine_name
The directive has no option. It extracts the routine signature, the
arguments with their types, shapes and attributes, and the description
comments, and inserts the corresponding f:function, f:subroutine or
f:interface directive, so f:autoroutine is the directive to use for
a generic interface.
f:autofunction and f:autosubroutine are equivalent (the parser keeps
a single index of routines, so both find any of them; only the text of the
warning for an unknown name differs).
Example
.. f:autoroutine:: linspace
which gives, for SF_ARRAYS:
.. f:function:: linspace(start, stop, num[, istart, iend, mesh])
Returns an array of evenly spaced numbers over a specified interval.
Returns :f:var:`num` evenly spaced samples, calculated over the interval [:f:var:`start`, :f:var:`stop`].
The start and end points of the interval can optionally be excluded.
:p real start: Starting value of the sequence
:p real stop: End value of the sequence
:p integer num: Number of samples to generate
:o logical istart: If :code:`.true.`, :f:var:`start` is included in the resulting array. Default :code:`.true.`
:o logical iend: If :code:`.true.`, :f:var:`stop` is included in the resulting array. Default :code:`.true.`
:o real mesh: If present, the step is saved in this variable
:r real array(num): Contains :f:var:`num` equally spaced samples in the interval [:f:var:`start`, :f:var:`stop`], left/right open or closed depending on :f:var:`istart` and :f:var:`iend`
If the name is not found, a warning is emitted (Wrong routine name,
Wrong function name, …) and the directive then fails with an error.
Note
Routines documented with an object directive are inserted after a
.. f:currentmodule:: line, so they are registered without a
module (as _/name). References by short name, such as
:f:func:`linspace`, resolve as usual.
.. f:autotype::
Document a Fortran derived type, with its components.
.. f:autotype:: point
The directive has no option. The type description and the components,
rendered as :f fields, are those of the source (see
Formatting Fortran (.f90) Code for Auto-Documentation, Derived Types). Type-bound procedures are not
documented.
.. f:autovariable::
Document a Fortran module variable.
.. f:autovariable:: beta
The directive has no option. It writes the f:variable directive with
the options :type:, :shape: and :attrs: deduced from the
declaration and the description of the source. A real example from
ED_INPUT_VARS, .. f:autovariable:: nbath:
.. f:variable:: nbath
Number of bath sites:
* :f:var:`bath_type` = :code:`normal` : number of bath sites per orbital
* :f:var:`bath_type` = :code:`hybrid` : total number of bath sites
* :f:var:`bath_type` = :code:`replica/general` : number of replicas
:Type: integer
:Bindings: Language = **c**, Name = **nbath**
:Default: 6
.. f:autoprogram::
Document a main program unit.
.. f:autoprogram:: main
The description block under the program line is used as for a routine,
and the use statements are listed in a :use: field.
.. f:autosrcfile::
Document all the objects defined in one source file: the program, the module and the stand-alone functions and subroutines, in that order.
.. f:autosrcfile:: solver.f90
:objtype: module
:search_mode: strict
Options
:objtype:Restrict to one of
program,module,functionorsubroutine. Only one value is understood.:search_mode:With
strict, the argument has to be the full path of the file as it was found byfortran_src. Otherwise (default) only the base name of the file is compared.
Warning
The argument is converted to lower case and then compared, with the
case preserved, to the file name. A file whose name contains capitals, such
as SF_ARRAYS.f90, is therefore never found and the warning
No valid content found for file is emitted. Files with a lower-case
name work, and so does :search_mode: strict with a fully lower-case
absolute path. Use f:automodule when in doubt.
Documentation Comments
Documentation is extracted from comments inside the documented entity (after its opening statement) and from the comment at the end of each declaration. See Formatting Fortran (.f90) Code for Auto-Documentation for the complete rules.
subroutine solve(A, b, x)
!Solve a linear system Ax = b using LU factorization without pivoting.
real, intent(in) :: A(:,:) !Coefficient matrix
real, intent(in) :: b(:) !Right-hand side
real, intent(out) :: x(:) !Solution
end subroutine solve
Comments written before the subroutine line, and Doxygen markers
(!>, !!), are not interpreted.
Automatic contents
The following information is deduced from the code and needs no comment:
the signature, with the optional arguments in square brackets;
the type, the shape and the attributes of each argument, of the result of a function, of each module variable and of each component of a type; the
intentis displayed, in brackets, in front of the other attributes;the default value of a variable initialised in its declaration;
the C bindings:
bind(c, name="x")on a variable or on a routine is displayed in a:Bindings:field;the
usestatements, inUsed modules(modules of the project),External modules(others) or in a:use:field for routines, including theonlylists andlocal => remoterenamings, which are displayed in the same direction, aslocal ⇒ remote;the arguments of a generic interface, merged from all its
module procedureimplementations.
Cross-Referencing
Documented entities can be referenced using Fortran-domain roles, in the
.rst files as well as in the Fortran comments:
:f:mod:`linalg`
:f:func:`linalg/solve`
:f:type:`matrix`
:f:var:`beta`
The text generated by the autodoc directives already contains such links: the
quick access lists, the use lists and the routine aliases. The roles are
detailed in Cross-Referencing. If a name is not defined in the project but
is found in an Intersphinx inventory that contains Fortran objects, the link
is made to that inventory.
Notes and Limitations
A generic interface is documented as one entry; its specific procedures are documented separately when they are public
Preprocessor conditionals are not evaluated
Accurate documentation depends on correct parsing of the Fortran source
Names must be given in lower case
Fortran files are not registered as dependencies of the pages (see Quick start)
Further behaviours that may surprise, with workarounds, are collected in Known limitations. For edge cases, manual use of the Fortran domain directives may provide greater control.