sphinx: support multiple output formats

formats (builders) can be passed as an array of strings.
keeps backwards compatibility if format is passed as string.
additionally support possibility to install the output of
the different builders to different directories
This commit is contained in:
Federico Pellegrin 2022-08-29 10:56:37 +02:00
parent bccfb03e76
commit 10c3ee7755
2 changed files with 41 additions and 21 deletions

View File

@ -7,4 +7,8 @@ def configure(cnf):
def build(bld): def build(bld):
bld(features='sphinx', sphinx_source='src', sphinx_output_format='html') # When multiple output format are given, the install_path_FMT can specify where to place a specific format, fallback is always on install_path
bld(features='sphinx', sphinx_source='src', sphinx_output_format=['html', 'info', 'man'], install_path_man='${DOCDIR}/man', install_path='${DOCDIR}')
# Old style syntax, with single format
# bld(features='sphinx', sphinx_source='src', sphinx_output_format='man')

View File

@ -1,7 +1,15 @@
"""Support for Sphinx documentation """Support for Sphinx documentation
This is a wrapper for sphinx-build program. Please note that sphinx-build supports only one output format which can This is a wrapper for sphinx-build program. Please note that sphinx-build supports only
passed to build via sphinx_output_format attribute. The default output format is html. one output format at a time, but the tool can create multiple tasks to handle more.
The output formats can be passed via the sphinx_output_format, which is an array of
strings. For backwards compatibility if only one output is needed, it can be passed
as a single string.
The default output format is html.
Specific formats can be installed in different directories by specifying the
install_path_<FORMAT> attribute. If not defined, the standard install_path
will be used instead.
Example wscript: Example wscript:
@ -13,7 +21,8 @@ def build(bld):
features='sphinx', features='sphinx',
sphinx_source='sources', # path to source directory sphinx_source='sources', # path to source directory
sphinx_options='-a -v', # sphinx-build program additional options sphinx_options='-a -v', # sphinx-build program additional options
sphinx_output_format='man' # output format of sphinx documentation sphinx_output_format=['html', 'man'], # output format of sphinx documentation
install_path_man='${DOCDIR}/man' # put man pages in a specific directory
) )
""" """
@ -43,35 +52,42 @@ def build_sphinx(self):
if not self.sphinx_source: if not self.sphinx_source:
self.bld.fatal('Can\'t find sphinx_source: %r' % self.sphinx_source) self.bld.fatal('Can\'t find sphinx_source: %r' % self.sphinx_source)
# In the taskgen we have the complete list of formats
Utils.def_attrs(self, sphinx_output_format='html') Utils.def_attrs(self, sphinx_output_format='html')
self.env.SPHINX_OUTPUT_FORMAT = self.sphinx_output_format self.sphinx_output_format = Utils.to_list(self.sphinx_output_format)
self.env.SPHINX_OPTIONS = getattr(self, 'sphinx_options', []) self.env.SPHINX_OPTIONS = getattr(self, 'sphinx_options', [])
for source_file in self.sphinx_source.ant_glob('**/*'): for source_file in self.sphinx_source.ant_glob('**/*'):
self.bld.add_manual_dependency(self.sphinx_source, source_file) self.bld.add_manual_dependency(self.sphinx_source, source_file)
sphinx_build_task = self.create_task('SphinxBuildingTask') for cfmt in self.sphinx_output_format:
sphinx_build_task.set_inputs(self.sphinx_source) sphinx_build_task = self.create_task('SphinxBuildingTask')
sphinx_build_task.set_outputs(self.path.get_bld()) sphinx_build_task.set_inputs(self.sphinx_source)
sphinx_build_task.set_outputs(self.path.get_bld())
# In task we keep the specific format this task is generating
sphinx_build_task.env.SPHINX_OUTPUT_FORMAT = cfmt
# the sphinx-build results are in <build + output_format> directory # the sphinx-build results are in <build + output_format> directory
self.sphinx_output_directory = self.path.get_bld().make_node(self.env.SPHINX_OUTPUT_FORMAT) sphinx_build_task.sphinx_output_directory = self.path.get_bld().make_node(cfmt)
self.sphinx_output_directory.mkdir() sphinx_build_task.sphinx_output_directory.mkdir()
Utils.def_attrs(self, install_path=get_install_path(self))
Utils.def_attrs(sphinx_build_task, install_path=getattr(self, 'install_path_' + cfmt, getattr(self, 'install_path', get_install_path(sphinx_build_task))))
def get_install_path(tg): def get_install_path(object):
if tg.env.SPHINX_OUTPUT_FORMAT == 'man': if object.env.SPHINX_OUTPUT_FORMAT == 'man':
return tg.env.MANDIR return object.env.MANDIR
elif tg.env.SPHINX_OUTPUT_FORMAT == 'info': elif object.env.SPHINX_OUTPUT_FORMAT == 'info':
return tg.env.INFODIR return object.env.INFODIR
else: else:
return tg.env.DOCDIR return object.env.DOCDIR
class SphinxBuildingTask(Task.Task): class SphinxBuildingTask(Task.Task):
color = 'BOLD' color = 'BOLD'
run_str = '${SPHINX_BUILD} -M ${SPHINX_OUTPUT_FORMAT} ${SRC} ${TGT} ${SPHINX_OPTIONS}' run_str = '${SPHINX_BUILD} -M ${SPHINX_OUTPUT_FORMAT} ${SRC} ${TGT} ${SPHINX_OPTIONS}'
no_errcheck_out = 'yes' # Needed for multiple formats uses same root out dir
def keyword(self): def keyword(self):
return 'Compiling (%s)' % self.env.SPHINX_OUTPUT_FORMAT return 'Compiling (%s)' % self.env.SPHINX_OUTPUT_FORMAT
@ -96,10 +112,10 @@ class SphinxBuildingTask(Task.Task):
def add_install(self): def add_install(self):
nodes = self.generator.sphinx_output_directory.ant_glob('**/*', quiet=True) nodes = self.sphinx_output_directory.ant_glob('**/*', quiet=True)
self.outputs += nodes self.outputs += nodes
self.generator.add_install_files(install_to=self.generator.install_path, self.generator.add_install_files(install_to=self.install_path,
install_from=nodes, install_from=nodes,
postpone=False, postpone=False,
cwd=self.generator.sphinx_output_directory, cwd=self.sphinx_output_directory,
relative_trick=True) relative_trick=True)