From 5e62a35f42bdc676476eb3c4b5302d0792460dfa Mon Sep 17 00:00:00 2001 From: Matt Williams Date: Wed, 14 Jul 2010 10:31:15 +0000 Subject: [PATCH] Add a CMakeLists.txt which provides the 'manual' target for building the Sphinx documentation. This may require you to set the SPHINXBUILD_EXECUTABLE CMake variable to the sphinx-build executable Change the file extension to 'rst' rather than 'txt' to avoid clashes with CMakeLists.txt and to help syntax highlighting. Add the doxylink Sphinx extension from sphinx-contrib to provide Doxygen links. --- CMakeLists.txt | 1 + documentation/CMakeLists.txt | 12 ++ .../_extensions/sphinxcontrib/LICENSE | 28 ++++ .../_extensions/sphinxcontrib/__init__.py | 14 ++ .../_extensions/sphinxcontrib/doxylink.py | 148 ++++++++++++++++++ documentation/{conf.py => conf.in.py} | 37 +++-- documentation/{index.txt => index.rst} | 0 7 files changed, 228 insertions(+), 12 deletions(-) create mode 100644 documentation/CMakeLists.txt create mode 100644 documentation/_extensions/sphinxcontrib/LICENSE create mode 100644 documentation/_extensions/sphinxcontrib/__init__.py create mode 100644 documentation/_extensions/sphinxcontrib/doxylink.py rename documentation/{conf.py => conf.in.py} (85%) rename documentation/{index.txt => index.rst} (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index a89c1473..8d905613 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -53,6 +53,7 @@ ELSE() SET(BUILD_AND_BUNDLE_DOCS NO) ENDIF() +ADD_SUBDIRECTORY(documentation) # Option summary MESSAGE(STATUS "") diff --git a/documentation/CMakeLists.txt b/documentation/CMakeLists.txt new file mode 100644 index 00000000..7f2d2c7f --- /dev/null +++ b/documentation/CMakeLists.txt @@ -0,0 +1,12 @@ +find_program(SPHINXBUILD_EXECUTABLE sphinx-build DOC "The location of the sphinx-build executable") + +if(SPHINXBUILD_EXECUTABLE AND QT_QCOLLECTIONGENERATOR_EXECUTABLE) + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/conf.in.py ${CMAKE_CURRENT_BINARY_DIR}/conf.py @ONLY) + #Generates the HTML docs and the Qt help file which can be opened with "assistant -collectionFile thermite.qhc" + #add_custom_target(manual ${SPHINXBUILD_EXECUTABLE} -b qthelp ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} COMMAND ${QT_QCOLLECTIONGENERATOR_EXECUTABLE} polyvox.qhcp -o polyvox.qhc) + add_custom_target(manual + ${SPHINXBUILD_EXECUTABLE} -b html + -c ${CMAKE_CURRENT_BINARY_DIR} #Load the conf.py from the binary dir + ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} + ) +endif() diff --git a/documentation/_extensions/sphinxcontrib/LICENSE b/documentation/_extensions/sphinxcontrib/LICENSE new file mode 100644 index 00000000..5a13a6a9 --- /dev/null +++ b/documentation/_extensions/sphinxcontrib/LICENSE @@ -0,0 +1,28 @@ +If not otherwise noted, the extensions in this package are licensed +under the following license. + +Copyright (c) 2010 Matt Williams. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/documentation/_extensions/sphinxcontrib/__init__.py b/documentation/_extensions/sphinxcontrib/__init__.py new file mode 100644 index 00000000..b5a7dc29 --- /dev/null +++ b/documentation/_extensions/sphinxcontrib/__init__.py @@ -0,0 +1,14 @@ +# -*- coding: utf-8 -*- +""" + sphinxcontrib + ~~~~~~~~~~~~~ + + This package is a namespace package that contains all extensions + distributed in the ``sphinx-contrib`` distribution. + + :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS. + :license: BSD, see LICENSE for details. +""" + +__import__('pkg_resources').declare_namespace(__name__) + diff --git a/documentation/_extensions/sphinxcontrib/doxylink.py b/documentation/_extensions/sphinxcontrib/doxylink.py new file mode 100644 index 00000000..0eedd15a --- /dev/null +++ b/documentation/_extensions/sphinxcontrib/doxylink.py @@ -0,0 +1,148 @@ +# -*- coding: utf-8 -*- +""" +doxylink +~~~~~~~~ + +Sphinx extension to link to external Doxygen API documentation. + +It works much like the extlinks extension but it does some more processing to link C++ symbols against their Doxygen HTML documentation. + +.. confval:: doxylink + + The environment is set up with a dictionary mapping the interpereted text role + to a tuple of tag file and prefix: + + .. code-block:: python + + doxylink = { + 'polyvox' : ('/home/matt/PolyVox.tag', '/home/matt/PolyVox/html/'), + 'qtogre' : ('/home/matt/QtOgre.tag', '/home/matt/QtOgre/html/'), + } + +This allows one to do: + +.. code-block:: rst + + :polyvox:`Array `. + :polyvox:`PolyVox::Volume` + :qtogre:`QtOgre::Log` + :polyvox:`tidyUpMemeory(int) ` + :polyvox:`PolyVox::Array::operator[]` + +:requires: Python 2.5 + +.. todo:: + + Make the extension atuomatically re-run if the tag file is altered on disc + + Find a way to parse the tag file to a DOM tree *once* and then just reference it from then on. + +:copyright: Copyright 2010 by Matt Williams +:license: BSD, see LICENSE for details. +""" + +from docutils import nodes, utils + +from sphinx.util.nodes import split_explicit_title + +import xml.etree.ElementTree as ET + +def find_url(doc, symbol): + """ + Return the URL for a given symbol. + + This is where the magic happens. + This function could be a lot more clever. At present it required the passed symbol to be almost exactly the same as the entries in the Doxygen tag file. + + .. todo:: + + Maybe print a list of all possible matches as a warning (but still only return the first) + + :Parameters: + doc : xml.etree.ElementTree + The XML DOM object + symbol : string + The symbol to lookup in the file. E.g. something like 'PolyVox::Array' or 'tidyUpMemory' + + :return: String representing the filename part of the URL + """ + + #First check for an exact match with a top-level object (namespaces, objects etc.) + + #env = inliner.document.settings.env + + matches = [] + for compound in doc.findall('.//compound'): + if compound.find('name').text == symbol: + matches += [compound.find('filename').text] + + if len(matches) > 1: + pass + #env.warn(env.docname, 'There were multiple matches for `%s`: %s' % (symbol, matches)) + if len(matches) == 1: + return matches[0] + + + #Strip off first namespace bit of the compound name so that 'ArraySizes' can match 'PolyVox::ArraySizes' + for compound in doc.findall('.//compound'): + symbol_list = compound.find('name').text.split('::', 1) + if len(symbol_list) == 2: + reducedsymbol = symbol_list[1] + if reducedsymbol == symbol: + return compound.find('filename').text + + #Now split the symbol by '::'. Find an exact match for the first part and then a member match for the second + #So PolyVox::Array::operator[] becomes like {namespace: "PolyVox::Array", endsymbol: "operator[]"} + symbol_list = symbol.rsplit('::', 1) + if len(symbol_list) == 2: + namespace = symbol_list[0] + endsymbol = symbol_list[1] + for compound in doc.findall('.//compound'): + if compound.find('name').text == namespace: + for member in compound.findall('member'): +# #If this compound object contains the matching member then return it + if member.find('name').text == endsymbol: + return member.find('anchorfile').text + '#' + member.find('anchor').text + + #Then we'll look at unqualified members + for member in doc.findall('.//member'): + if member.find('name').text == symbol: + return member.find('anchorfile').text + '#' + member.find('anchor').text + + return None + +def create_role(app, tag_filename, rootdir): + def find_doxygen_link(name, rawtext, text, lineno, inliner, options={}, content=[]): + text = utils.unescape(text) + # from :name:`title ` + has_explicit_title, title, part = split_explicit_title(text) + + try: + tag_file = ET.parse(tag_filename) + except (IOError): + env = inliner.document.settings.env + env.warn(env.docname, 'Could not open %s' % tag_filename) + else: + url = find_url(tag_file, part) + if url: + full_url = rootdir + url + pnode = nodes.reference(title, title, internal=False, refuri=full_url) + return [pnode], [] + #By here, no match was found + env = app.env + env.warn(env.docname, 'Could not find match for `%s` in `%s` tag file' % (part, tag_filename), lineno) + + full_url="#" + #TODO find which command to use to just output it as plain text (no link) in this case + pnode = nodes.reference(title, title, internal=False, refuri=full_url) + return [pnode], [] + + return find_doxygen_link + +def setup_doxylink_roles(app): + for name, [tag_filename, rootdir] in app.config.doxylink.iteritems(): + app.add_role(name, create_role(app, tag_filename, rootdir)) + +def setup(app): + app.add_config_value('doxylink', {}, 'env') + app.connect('builder-inited', setup_doxylink_roles) diff --git a/documentation/conf.py b/documentation/conf.in.py similarity index 85% rename from documentation/conf.py rename to documentation/conf.in.py index c3587b49..93b7d6aa 100644 --- a/documentation/conf.py +++ b/documentation/conf.in.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # # PolyVox documentation build configuration file, created by -# sphinx-quickstart on Tue Jul 13 21:12:07 2010. +# sphinx-quickstart on Tue Jul 6 14:46:57 2010. # # This file is execfile()d with the current directory set to its containing dir. # @@ -16,7 +16,7 @@ import sys, os # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. -#sys.path.append(os.path.abspath('.')) +sys.path.append('@CMAKE_CURRENT_SOURCE_DIR@/_extensions') # -- General configuration ----------------------------------------------------- @@ -25,13 +25,13 @@ import sys, os # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = [] +extensions = ['sphinxcontrib.doxylink'] # Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] +templates_path = ['@CMAKE_CURRENT_SOURCE_DIR@/_templates'] # The suffix of source filenames. -source_suffix = '.txt' +source_suffix = '.rst' # The encoding of source files. #source_encoding = 'utf-8-sig' @@ -41,16 +41,16 @@ master_doc = 'index' # General information about the project. project = u'PolyVox' -copyright = u'2010, David Williams Matt Williams' +copyright = u'2010, David Williams, Matt Williams' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. -version = '1.0' +version = '@POLYVOX_VERSION@' # The full version, including alpha/beta/rc tags. -release = '1.0' +release = '@POLYVOX_VERSION@' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. @@ -120,7 +120,7 @@ html_theme = 'default' # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] +html_static_path = ['@CMAKE_CURRENT_SOURCE_DIR@/_static'] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. @@ -164,7 +164,7 @@ html_static_path = ['_static'] #html_file_suffix = '' # Output file base name for HTML help builder. -htmlhelp_basename = 'PolyVoxdoc' +#htmlhelp_basename = 'PolyVoxdoc' # -- Options for LaTeX output -------------------------------------------------- @@ -179,7 +179,7 @@ htmlhelp_basename = 'PolyVoxdoc' # (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [ ('index', 'PolyVox.tex', u'PolyVox Documentation', - u'David Williams Matt Williams', 'manual'), + u'David Williams, Matt Williams', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of @@ -212,5 +212,18 @@ latex_documents = [ # (source start file, name, description, authors, manual section). man_pages = [ ('index', 'polyvox', u'PolyVox Documentation', - [u'David Williams Matt Williams'], 1) + [u'David Williams, Matt Williams'], 1) ] + + +# Example configuration for intersphinx: refer to the Python standard library. +#intersphinx_mapping = {'http://docs.python.org/': None} + +doxylink = { + 'polyvox' : ('@CMAKE_CURRENT_BINARY_DIR@/../library/PolyVox.tag', '../library/doc/html/') +} + +#This must be lowercase for QtHelp +qthelp_basename = "polyvox" + +primary_domain = "c++" diff --git a/documentation/index.txt b/documentation/index.rst similarity index 100% rename from documentation/index.txt rename to documentation/index.rst