[v15,5/5] dts: add API doc generation
Checks
Commit Message
The tool used to generate DTS API docs is Sphinx, which is already in
use in DPDK. The same configuration is used to preserve style with one
DTS-specific configuration (so that the DPDK docs are unchanged) that
modifies how the sidebar displays the content.
Sphinx generates the documentation from Python docstrings. The docstring
format is the Google format [0] which requires the sphinx.ext.napoleon
extension. The other extension, sphinx.ext.intersphinx, enables linking
to objects in external documentations, such as the Python documentation.
There is one requirement for building DTS docs - the same Python version
as DTS or higher, because Sphinx's autodoc extension imports the code.
The dependencies needed to import the code don't have to be satisfied,
as the autodoc extension allows us to mock the imports. The missing
packages are taken from the DTS pyproject.toml file.
[0] https://google.github.io/styleguide/pyguide.html#38-comments-and-docstrings
Signed-off-by: Juraj Linkeš <juraj.linkes@pantheon.tech>
---
buildtools/call-sphinx-build.py | 2 +
buildtools/get-dts-deps.py | 78 +++++++++++++++++++++++
buildtools/meson.build | 1 +
doc/api/doxy-api-index.md | 3 +
doc/api/doxy-api.conf.in | 2 +
doc/api/dts/custom.css | 1 +
doc/api/dts/meson.build | 29 +++++++++
doc/api/meson.build | 13 ++++
doc/guides/conf.py | 41 +++++++++++-
doc/guides/contributing/documentation.rst | 2 +
doc/guides/contributing/patches.rst | 4 ++
doc/guides/tools/dts.rst | 39 +++++++++++-
doc/meson.build | 1 +
13 files changed, 214 insertions(+), 2 deletions(-)
create mode 100755 buildtools/get-dts-deps.py
create mode 120000 doc/api/dts/custom.css
create mode 100644 doc/api/dts/meson.build
Comments
06/08/2024 17:19, Juraj Linkeš:
> +"""Utilities for DTS dependencies.
> +
> +The module can be used as an executable script,
> +which verifies that the running Python version meets the version requirement of DTS.
> +The script returns the standard exit codes in this mode (0 is success, 1 is failure).
Is it returning the list of dependencies for generating doc?
> +
> +The module also contains a function, get_missing_imports,
> +which looks for runtime and doc generation dependencies in the DTS pyproject.toml file
> +a returns a list of module names used in an import statement that are missing.
typo? a -> and
[...]
> +get_dts_deps = py3 + files('get-dts-deps.py')
deps for runtime or doc?
may be good to specify in the name
> --- /dev/null
> +++ b/doc/api/dts/custom.css
> @@ -0,0 +1 @@
> +../../guides/custom.css
> \ No newline at end of file
Is it a link? Why?
> +htmldir = join_paths(get_option('datadir'), 'doc', 'dpdk', 'dts')
> +dts_api_html = custom_target('dts_api_html',
> + output: 'html',
> + command: [sphinx_wrapper, sphinx, meson.project_version(),
> + meson.current_source_dir(), meson.current_build_dir(), extra_sphinx_args],
> + build_by_default: get_option('enable_docs'),
> + install: get_option('enable_docs'),
> + install_dir: htmldir)
When custom.css is copied?
> +# Napoleon enables the Google format of Python doscstrings, used in DTS.
> +# Intersphinx allows linking to external projects, such as Python docs, also used in DTS.
> +extensions = ['sphinx.ext.napoleon', 'sphinx.ext.intersphinx']
What happens if napoleon and intersphinx are not available
when building basic DPDK doc without DTS?
On 7. 8. 2024 12:41, Thomas Monjalon wrote:
> 06/08/2024 17:19, Juraj Linkeš:
>> +"""Utilities for DTS dependencies.
>> +
>> +The module can be used as an executable script,
>> +which verifies that the running Python version meets the version requirement of DTS.
>> +The script returns the standard exit codes in this mode (0 is success, 1 is failure).
>
> Is it returning the list of dependencies for generating doc?
>
It's not worded right. When run as a script, it exits with the standard
exit codes, it doesn't return anything.
The function below is for returning the list of depedencies.
>> +
>> +The module also contains a function, get_missing_imports,
>> +which looks for runtime and doc generation dependencies in the DTS pyproject.toml file
>> +a returns a list of module names used in an import statement that are missing.
>
> typo? a -> and
Ack.
>
> [...]
>> +get_dts_deps = py3 + files('get-dts-deps.py')
>
> deps for runtime or doc?
> may be good to specify in the name
>
It's getting both, actually.
Now that I think about it, we don't need to get the docs dependencies,
as we check for Sphinx elsewhere. We really only need to get the runtime
dependencies and mock what's missing (that is add those to the
autodoc_mock_imports config option).
I think it makes sense to change the script and rename it to
get-dts-runtime-deps.py (and the variable).
>
>> --- /dev/null
>> +++ b/doc/api/dts/custom.css
>> @@ -0,0 +1 @@
>> +../../guides/custom.css
>> \ No newline at end of file
>
> Is it a link? Why?
>
call-sphinx-build.py copies the custom.css file. I added a link to
preserve the look.
>> +htmldir = join_paths(get_option('datadir'), 'doc', 'dpdk', 'dts')
>> +dts_api_html = custom_target('dts_api_html',
>> + output: 'html',
>> + command: [sphinx_wrapper, sphinx, meson.project_version(),
>> + meson.current_source_dir(), meson.current_build_dir(), extra_sphinx_args],
>> + build_by_default: get_option('enable_docs'),
>> + install: get_option('enable_docs'),
>> + install_dir: htmldir)
>
> When custom.css is copied?
>
I'm not sure what you're asking here. The call-sphinx-build.py copies it
during the build and it's also copied during the install phase.
>
>
>> +# Napoleon enables the Google format of Python doscstrings, used in DTS.
>> +# Intersphinx allows linking to external projects, such as Python docs, also used in DTS.
>> +extensions = ['sphinx.ext.napoleon', 'sphinx.ext.intersphinx']
>
> What happens if napoleon and intersphinx are not available
> when building basic DPDK doc without DTS?
>
>
napoleon was added in version 1.3 and intersphinx in 0.5, so I didn't
think of testing that.
I tried adding a non-existent extension to the list and got this error:
Extension error:
Could not import extension sphinx.ext.foo (exception: No module named
'sphinx.ext.foo')
I could add version checks for each of the extensions.
07/08/2024 14:03, Juraj Linkeš:
> On 7. 8. 2024 12:41, Thomas Monjalon wrote:
> > 06/08/2024 17:19, Juraj Linkeš:
> > [...]
> >> +get_dts_deps = py3 + files('get-dts-deps.py')
> >
> > deps for runtime or doc?
> > may be good to specify in the name
> >
>
> It's getting both, actually.
> Now that I think about it, we don't need to get the docs dependencies,
> as we check for Sphinx elsewhere. We really only need to get the runtime
> dependencies and mock what's missing (that is add those to the
> autodoc_mock_imports config option).
>
> I think it makes sense to change the script and rename it to
> get-dts-runtime-deps.py (and the variable).
OK
> >> --- /dev/null
> >> +++ b/doc/api/dts/custom.css
> >> @@ -0,0 +1 @@
> >> +../../guides/custom.css
> >> \ No newline at end of file
> >
> > Is it a link? Why?
> >
>
> call-sphinx-build.py copies the custom.css file. I added a link to
> preserve the look.
>
> >> +htmldir = join_paths(get_option('datadir'), 'doc', 'dpdk', 'dts')
> >> +dts_api_html = custom_target('dts_api_html',
> >> + output: 'html',
> >> + command: [sphinx_wrapper, sphinx, meson.project_version(),
> >> + meson.current_source_dir(), meson.current_build_dir(), extra_sphinx_args],
> >> + build_by_default: get_option('enable_docs'),
> >> + install: get_option('enable_docs'),
> >> + install_dir: htmldir)
> >
> > When custom.css is copied?
>
> I'm not sure what you're asking here. The call-sphinx-build.py copies it
> during the build and it's also copied during the install phase.
The file is copied in _static dir of sphinx guides.
How does it work for DTS API?
> >> +# Napoleon enables the Google format of Python doscstrings, used in DTS.
> >> +# Intersphinx allows linking to external projects, such as Python docs, also used in DTS.
> >> +extensions = ['sphinx.ext.napoleon', 'sphinx.ext.intersphinx']
> >
> > What happens if napoleon and intersphinx are not available
> > when building basic DPDK doc without DTS?
>
> napoleon was added in version 1.3 and intersphinx in 0.5, so I didn't
> think of testing that.
>
> I tried adding a non-existent extension to the list and got this error:
> Extension error:
> Could not import extension sphinx.ext.foo (exception: No module named
> 'sphinx.ext.foo')
>
> I could add version checks for each of the extensions.
My concern is to allow generating DPDK doc without DTS,
without the new extra dependencies.
On 7. 8. 2024 14:27, Thomas Monjalon wrote:
> 07/08/2024 14:03, Juraj Linkeš:
>> On 7. 8. 2024 12:41, Thomas Monjalon wrote:
>>> 06/08/2024 17:19, Juraj Linkeš:
>>> [...]
>>>> +get_dts_deps = py3 + files('get-dts-deps.py')
>>>
>>> deps for runtime or doc?
>>> may be good to specify in the name
>>>
>>
>> It's getting both, actually.
>> Now that I think about it, we don't need to get the docs dependencies,
>> as we check for Sphinx elsewhere. We really only need to get the runtime
>> dependencies and mock what's missing (that is add those to the
>> autodoc_mock_imports config option).
>>
>> I think it makes sense to change the script and rename it to
>> get-dts-runtime-deps.py (and the variable).
>
> OK
>
>>>> --- /dev/null
>>>> +++ b/doc/api/dts/custom.css
>>>> @@ -0,0 +1 @@
>>>> +../../guides/custom.css
>>>> \ No newline at end of file
>>>
>>> Is it a link? Why?
>>>
>>
>> call-sphinx-build.py copies the custom.css file. I added a link to
>> preserve the look.
>>
>>>> +htmldir = join_paths(get_option('datadir'), 'doc', 'dpdk', 'dts')
>>>> +dts_api_html = custom_target('dts_api_html',
>>>> + output: 'html',
>>>> + command: [sphinx_wrapper, sphinx, meson.project_version(),
>>>> + meson.current_source_dir(), meson.current_build_dir(), extra_sphinx_args],
>>>> + build_by_default: get_option('enable_docs'),
>>>> + install: get_option('enable_docs'),
>>>> + install_dir: htmldir)
>>>
>>> When custom.css is copied?
>>
>> I'm not sure what you're asking here. The call-sphinx-build.py copies it
>> during the build and it's also copied during the install phase.
>
> The file is copied in _static dir of sphinx guides.
> How does it work for DTS API?
>
It works the same way. shutil.copyfile (which is used to copy the file)
follows symlinks, so DTS API gets a copy in its _static dir
(doc/api/dts/html/_static/css).
I did it this way to preserve the style in case there's something in the
css file that applies to both DPDK and DTS API docs.
>
>>>> +# Napoleon enables the Google format of Python doscstrings, used in DTS.
>>>> +# Intersphinx allows linking to external projects, such as Python docs, also used in DTS.
>>>> +extensions = ['sphinx.ext.napoleon', 'sphinx.ext.intersphinx']
>>>
>>> What happens if napoleon and intersphinx are not available
>>> when building basic DPDK doc without DTS?
>>
>> napoleon was added in version 1.3 and intersphinx in 0.5, so I didn't
>> think of testing that.
>>
>> I tried adding a non-existent extension to the list and got this error:
>> Extension error:
>> Could not import extension sphinx.ext.foo (exception: No module named
>> 'sphinx.ext.foo')
>>
>> I could add version checks for each of the extensions.
>
> My concern is to allow generating DPDK doc without DTS,
> without the new extra dependencies.
>
Ok, I think putting all of these into the DTS if branch ("if
environ.get('DTS_BUILD'):") would make sense then.
07/08/2024 15:12, Juraj Linkeš:
> On 7. 8. 2024 14:27, Thomas Monjalon wrote:
> > 07/08/2024 14:03, Juraj Linkeš:
> >> On 7. 8. 2024 12:41, Thomas Monjalon wrote:
> >>> 06/08/2024 17:19, Juraj Linkeš:
> >>>> --- /dev/null
> >>>> +++ b/doc/api/dts/custom.css
> >>>> @@ -0,0 +1 @@
> >>>> +../../guides/custom.css
> >>>> \ No newline at end of file
> >>>
> >>> Is it a link? Why?
> >>>
> >>
> >> call-sphinx-build.py copies the custom.css file. I added a link to
> >> preserve the look.
> >>
> >>>> +htmldir = join_paths(get_option('datadir'), 'doc', 'dpdk', 'dts')
> >>>> +dts_api_html = custom_target('dts_api_html',
> >>>> + output: 'html',
> >>>> + command: [sphinx_wrapper, sphinx, meson.project_version(),
> >>>> + meson.current_source_dir(), meson.current_build_dir(), extra_sphinx_args],
> >>>> + build_by_default: get_option('enable_docs'),
> >>>> + install: get_option('enable_docs'),
> >>>> + install_dir: htmldir)
> >>>
> >>> When custom.css is copied?
> >>
> >> I'm not sure what you're asking here. The call-sphinx-build.py copies it
> >> during the build and it's also copied during the install phase.
> >
> > The file is copied in _static dir of sphinx guides.
> > How does it work for DTS API?
>
> It works the same way. shutil.copyfile (which is used to copy the file)
> follows symlinks, so DTS API gets a copy in its _static dir
> (doc/api/dts/html/_static/css).
> I did it this way to preserve the style in case there's something in the
> css file that applies to both DPDK and DTS API docs.
Oh yes.
I wrote it 2 weeks ago and already forgot it works with any sphinx path.
> >>>> +# Napoleon enables the Google format of Python doscstrings, used in DTS.
> >>>> +# Intersphinx allows linking to external projects, such as Python docs, also used in DTS.
> >>>> +extensions = ['sphinx.ext.napoleon', 'sphinx.ext.intersphinx']
> >>>
> >>> What happens if napoleon and intersphinx are not available
> >>> when building basic DPDK doc without DTS?
> >>
> >> napoleon was added in version 1.3 and intersphinx in 0.5, so I didn't
> >> think of testing that.
> >>
> >> I tried adding a non-existent extension to the list and got this error:
> >> Extension error:
> >> Could not import extension sphinx.ext.foo (exception: No module named
> >> 'sphinx.ext.foo')
> >>
> >> I could add version checks for each of the extensions.
> >
> > My concern is to allow generating DPDK doc without DTS,
> > without the new extra dependencies.
> >
>
> Ok, I think putting all of these into the DTS if branch ("if
> environ.get('DTS_BUILD'):") would make sense then.
OK
@@ -15,6 +15,8 @@
# set the version in environment for sphinx to pick up
os.environ['DPDK_VERSION'] = version
+if src.find('dts') != -1:
+ os.environ['DTS_BUILD'] = "y"
sphinx_cmd = [sphinx] + extra_args
new file mode 100755
@@ -0,0 +1,78 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2024 PANTHEON.tech s.r.o.
+#
+
+"""Utilities for DTS dependencies.
+
+The module can be used as an executable script,
+which verifies that the running Python version meets the version requirement of DTS.
+The script returns the standard exit codes in this mode (0 is success, 1 is failure).
+
+The module also contains a function, get_missing_imports,
+which looks for runtime and doc generation dependencies in the DTS pyproject.toml file
+a returns a list of module names used in an import statement that are missing.
+"""
+
+import configparser
+import importlib.metadata
+import importlib.util
+import os.path
+import platform
+
+_VERSION_COMPARISON_CHARS = '^<>='
+_EXTRA_DEPS = {'invoke': '>=1.3', 'paramiko': '>=2.4'}
+_DPDK_ROOT = os.path.dirname(os.path.dirname(__file__))
+_DTS_DEP_FILE_PATH = os.path.join(_DPDK_ROOT, 'dts', 'pyproject.toml')
+
+
+def _get_version_tuple(version_str):
+ return tuple(map(int, version_str.split(".")))
+
+
+def _get_dependencies(cfg_file_path):
+ cfg = configparser.ConfigParser()
+ with open(cfg_file_path) as f:
+ dts_deps_file_str = f.read()
+ dts_deps_file_str = dts_deps_file_str.replace("\n]", "]")
+ cfg.read_string(dts_deps_file_str)
+
+ deps_section = cfg['tool.poetry.dependencies']
+ deps = {dep: deps_section[dep].strip('"\'') for dep in deps_section}
+ doc_deps_section = cfg['tool.poetry.group.docs.dependencies']
+ doc_deps = {dep: doc_deps_section[dep].strip("\"'") for dep in doc_deps_section}
+
+ return deps | doc_deps
+
+
+def get_missing_imports():
+ missing_imports = []
+ req_deps = _get_dependencies(_DTS_DEP_FILE_PATH)
+ req_deps.pop('python')
+
+ for req_dep, req_ver in (req_deps | _EXTRA_DEPS).items():
+ try:
+ req_ver = _get_version_tuple(req_ver.strip(_VERSION_COMPARISON_CHARS))
+ found_dep_ver = _get_version_tuple(importlib.metadata.version(req_dep))
+ if found_dep_ver < req_ver:
+ print(
+ f'The version "{found_dep_ver}" of package "{req_dep}" '
+ f'is lower than required "{req_ver}".'
+ )
+ except importlib.metadata.PackageNotFoundError:
+ print(f'Package "{req_dep}" not found.')
+ missing_imports.append(req_dep.lower().replace('-', '_'))
+
+ return missing_imports
+
+
+if __name__ == '__main__':
+ python_version = _get_dependencies(_DTS_DEP_FILE_PATH).pop('python')
+ if python_version:
+ sys_ver = _get_version_tuple(platform.python_version())
+ req_ver = _get_version_tuple(python_version.strip(_VERSION_COMPARISON_CHARS))
+ if sys_ver < req_ver:
+ print(
+ f'The available Python version "{sys_ver}" is lower than required "{req_ver}".'
+ )
+ exit(1)
@@ -24,6 +24,7 @@ get_numa_count_cmd = py3 + files('get-numa-count.py')
get_test_suites_cmd = py3 + files('get-test-suites.py')
has_hugepages_cmd = py3 + files('has-hugepages.py')
cmdline_gen_cmd = py3 + files('dpdk-cmdline-gen.py')
+get_dts_deps = py3 + files('get-dts-deps.py')
# install any build tools that end-users might want also
install_data([
@@ -245,3 +245,6 @@ The public API headers are grouped by topics:
[experimental APIs](@ref rte_compat.h),
[ABI versioning](@ref rte_function_versioning.h),
[version](@ref rte_version.h)
+
+- **tests**:
+ [**DTS**](@dts_api_main_page)
@@ -124,6 +124,8 @@ SEARCHENGINE = YES
SORT_MEMBER_DOCS = NO
SOURCE_BROWSER = YES
+ALIASES = "dts_api_main_page=@DTS_API_MAIN_PAGE@"
+
EXAMPLE_PATH = @TOPDIR@/examples
EXAMPLE_PATTERNS = *.c
EXAMPLE_RECURSIVE = YES
new file mode 120000
@@ -0,0 +1 @@
+../../guides/custom.css
\ No newline at end of file
new file mode 100644
@@ -0,0 +1,29 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2023 PANTHEON.tech s.r.o.
+
+sphinx = find_program('sphinx-build', required: get_option('enable_docs'))
+if not sphinx.found()
+ subdir_done()
+endif
+
+python_ver_satisfied = run_command(get_dts_deps).returncode()
+if python_ver_satisfied != 0
+ subdir_done()
+endif
+
+extra_sphinx_args = ['-E', '-c', join_paths(doc_source_dir, 'guides')]
+if get_option('werror')
+ extra_sphinx_args += '-W'
+endif
+
+htmldir = join_paths(get_option('datadir'), 'doc', 'dpdk', 'dts')
+dts_api_html = custom_target('dts_api_html',
+ output: 'html',
+ command: [sphinx_wrapper, sphinx, meson.project_version(),
+ meson.current_source_dir(), meson.current_build_dir(), extra_sphinx_args],
+ build_by_default: get_option('enable_docs'),
+ install: get_option('enable_docs'),
+ install_dir: htmldir)
+
+dts_doc_targets += dts_api_html
+dts_doc_target_names += 'DTS_API_HTML'
@@ -1,6 +1,18 @@
# SPDX-License-Identifier: BSD-3-Clause
# Copyright(c) 2018 Luca Boccassi <bluca@debian.org>
+dts_doc_targets = []
+dts_doc_target_names = []
+subdir('dts')
+
+if dts_doc_targets.length() == 0
+ dts_message = 'No DTS docs targets found'
+else
+ dts_message = 'Building DTS docs:'
+endif
+run_target('dts-doc', command: [echo, dts_message, dts_doc_target_names],
+ depends: dts_doc_targets)
+
doxygen = find_program('doxygen', required: get_option('enable_docs'))
if not doxygen.found()
@@ -40,6 +52,7 @@ cdata.set('WARN_AS_ERROR', 'NO')
if get_option('werror')
cdata.set('WARN_AS_ERROR', 'YES')
endif
+cdata.set('DTS_API_MAIN_PAGE', join_paths('..', 'dts', 'html', 'index.html'))
# configure HTML Doxygen run
html_cdata = configuration_data()
@@ -10,7 +10,7 @@
from os.path import basename
from os.path import dirname
from os.path import join as path_join
-from sys import argv, stderr
+from sys import argv, stderr, path
import configparser
@@ -24,6 +24,45 @@
file=stderr)
pass
+# Napoleon enables the Google format of Python doscstrings, used in DTS.
+# Intersphinx allows linking to external projects, such as Python docs, also used in DTS.
+extensions = ['sphinx.ext.napoleon', 'sphinx.ext.intersphinx']
+
+# DTS Python docstring options.
+autodoc_default_options = {
+ 'members': True,
+ 'member-order': 'bysource',
+ 'show-inheritance': True,
+}
+autodoc_class_signature = 'separated'
+autodoc_typehints = 'both'
+autodoc_typehints_format = 'short'
+autodoc_typehints_description_target = 'documented'
+napoleon_numpy_docstring = False
+napoleon_attr_annotations = True
+napoleon_preprocess_types = True
+add_module_names = False
+toc_object_entries = True
+toc_object_entries_show_parents = 'hide'
+intersphinx_mapping = {'python': ('https://docs.python.org/3', None)}
+
+if environ.get('DTS_BUILD'):
+ # Add path to DTS sources so that Sphinx can find them.
+ dpdk_root = dirname(dirname(dirname(__file__)))
+ path.append(path_join(dpdk_root, 'dts'))
+
+ # Get missing DTS dependencies. Add path to buildtools to find the get_missing_imports function.
+ path.append(path_join(dpdk_root, 'buildtools'))
+ import importlib
+ # Ignore missing imports from DTS dependencies.
+ autodoc_mock_imports = importlib.import_module('get-dts-deps').get_missing_imports()
+
+ # DTS Sidebar config.
+ html_theme_options = {
+ 'collapse_navigation': False,
+ 'navigation_depth': -1, # unlimited depth
+ }
+
stop_on_error = ('-W' in argv)
project = 'Data Plane Development Kit'
@@ -133,6 +133,8 @@ added to by the developer.
Building the Documentation
--------------------------
+.. _doc_dependencies:
+
Dependencies
~~~~~~~~~~~~
@@ -499,6 +499,10 @@ The script usage is::
For both of the above scripts, the -n option is used to specify a number of commits from HEAD,
and the -r option allows the user specify a ``git log`` range.
+Additionally, when contributing to the DTS tool, patches should also be checked using
+the ``dts-check-format.sh`` script in the ``devtools`` directory of the DPDK repo.
+To run the script, extra :ref:`Python dependencies <dts_deps>` are needed.
+
.. _contrib_check_compilation:
Checking Compilation
@@ -54,6 +54,7 @@ DTS uses Poetry as its Python dependency management.
Python build/development and runtime environments are the same and DTS development environment,
DTS runtime environment or just plain DTS environment are used interchangeably.
+.. _dts_deps:
Setting up DTS environment
~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -291,8 +292,15 @@ When adding code to the DTS framework, pay attention to the rest of the code
and try not to divert much from it.
The :ref:`DTS developer tools <dts_dev_tools>` will issue warnings
when some of the basics are not met.
+You should also build the :ref:`API documentation <building_api_docs>`
+to address any issues found during the build.
-The code must be properly documented with docstrings.
+The API documentation, which is a helpful reference when developing, may be accessed
+in the code directly or generated with the :ref:`API docs build steps <building_api_docs>`.
+When adding new files or modifying the directory structure,
+the corresponding changes must be made to DTS api doc sources in ``doc/api/dts``.
+
+Speaking of which, the code must be properly documented with docstrings.
The style must conform to the `Google style
<https://google.github.io/styleguide/pyguide.html#38-comments-and-docstrings>`_.
See an example of the style `here
@@ -427,6 +435,35 @@ the DTS code check and format script.
Refer to the script for usage: ``devtools/dts-check-format.sh -h``.
+.. _building_api_docs:
+
+Building DTS API docs
+---------------------
+
+The documentation is built using the standard DPDK build system.
+See :doc:`../linux_gsg/build_dpdk` for more details on compiling DPDK with meson.
+
+The :ref:`doc build dependencies <doc_dependencies>` may be installed with Poetry:
+
+.. code-block:: console
+
+ poetry install --no-root --only docs
+ poetry install --no-root --with docs # an alternative that will also install DTS dependencies
+ poetry shell
+
+After executing the meson command, build the documentation with:
+
+.. code-block:: console
+
+ ninja -C build dts-doc
+
+The output is generated in ``build/doc/api/dts/html``.
+
+.. note::
+
+ Make sure to fix any Sphinx warnings when adding or updating docstrings.
+
+
Configuration Schema
--------------------
@@ -1,6 +1,7 @@
# SPDX-License-Identifier: BSD-3-Clause
# Copyright(c) 2018 Luca Boccassi <bluca@debian.org>
+doc_source_dir = meson.current_source_dir()
doc_targets = []
doc_target_names = []
subdir('api')