From fcda5f921ef463c23d94785d1d25ede1600884cd Mon Sep 17 00:00:00 2001 From: Ken Conley Date: Wed, 23 Sep 2009 03:18:01 +0000 Subject: [PATCH] rosdoc: ported rosdoc to new config-style system for non-doxygen builds and added landing page for packages with multiple documentation sets. Also removed msgenator from doxygenator build. Much still to do with rosdoc in terms of refactoring doxygenator and also giving landing page better look and feel --- core/roslib/manifest.xml | 3 +- core/roslib/rosdoc.yaml | 6 + core/rospy/manifest.xml | 2 +- core/rospy/rosdoc.yaml | 1 + tools/rosdoc/src/rosdoc/__init__.py | 13 +- tools/rosdoc/src/rosdoc/doxygenator.py | 152 ++++++++++++------------ tools/rosdoc/src/rosdoc/epyenator.py | 27 +++-- tools/rosdoc/src/rosdoc/landing_page.py | 130 ++++++++++++++++++++ tools/rosdoc/src/rosdoc/rdcore.py | 44 +++++-- tools/rosdoc/src/rosdoc/sphinxenator.py | 15 ++- tools/rosdoc/templates/doxy.template | 4 +- tools/rosdoc/templates/landing.template | 17 +++ tools/rosdoc/templates/manifest.html | 3 - tools/rosservice/manifest.xml | 2 +- tools/rosservice/rosdoc.yaml | 1 + tools/rostopic/manifest.xml | 2 +- tools/rostopic/rosdoc.yaml | 1 + 17 files changed, 311 insertions(+), 112 deletions(-) create mode 100644 core/roslib/rosdoc.yaml create mode 100644 core/rospy/rosdoc.yaml create mode 100644 tools/rosdoc/src/rosdoc/landing_page.py create mode 100644 tools/rosdoc/templates/landing.template create mode 100644 tools/rosservice/rosdoc.yaml create mode 100644 tools/rostopic/rosdoc.yaml diff --git a/core/roslib/manifest.xml b/core/roslib/manifest.xml index 849e1c2f..98001bc1 100644 --- a/core/roslib/manifest.xml +++ b/core/roslib/manifest.xml @@ -7,9 +7,10 @@ Ken Conley/kwc@willowgarage.com, Morgan Quigley/mquigley@cs.stanford.edu BSD - http://pr.willowgarage.com/wiki/roslib + http://ros.org/wiki/roslib + diff --git a/core/roslib/rosdoc.yaml b/core/roslib/rosdoc.yaml new file mode 100644 index 00000000..97bf9687 --- /dev/null +++ b/core/roslib/rosdoc.yaml @@ -0,0 +1,6 @@ + - builder: epydoc + output_dir: python + - builder: doxygen + name: C++ API + output_dir: c++ + file_patterns: '*.c *.cpp *.h *.cc *.hh *.dox' \ No newline at end of file diff --git a/core/rospy/manifest.xml b/core/rospy/manifest.xml index 4dcd357b..cadb95c0 100644 --- a/core/rospy/manifest.xml +++ b/core/rospy/manifest.xml @@ -31,7 +31,7 @@ - + diff --git a/core/rospy/rosdoc.yaml b/core/rospy/rosdoc.yaml new file mode 100644 index 00000000..0bdea97f --- /dev/null +++ b/core/rospy/rosdoc.yaml @@ -0,0 +1 @@ + - builder: epydoc diff --git a/tools/rosdoc/src/rosdoc/__init__.py b/tools/rosdoc/src/rosdoc/__init__.py index e03f0794..66099ee1 100644 --- a/tools/rosdoc/src/rosdoc/__init__.py +++ b/tools/rosdoc/src/rosdoc/__init__.py @@ -84,11 +84,10 @@ def main(): else: sphinx_success = set() - # Generate Doxygen on remainder + # Generate Doxygen if 1: print "building doxygen packages" import doxygenator - ctx.packages = dict([(p, ctx.packages[p]) for p in (set(ctx.packages) - sphinx_success - epyenator_success)]) doxy_success = doxygenator.generate_doxygen(ctx, quiet=options.quiet) else: doxy_success = [] @@ -109,6 +108,11 @@ def main(): traceback.print_exc() print >> sys.stderr, "msgenator failed" + if 1: + # Generate landing page + import landing_page + landing_page.generate_landing_page(ctx) + if 1: # Generate Documentation Index import docindex @@ -128,10 +132,5 @@ def main(): styles_css = os.path.join(ctx.docdir, 'styles.css') print "copying",styles_in, "to", styles_css shutil.copyfile(styles_in, styles_css) - - # have to copy doxygen.css for external packages that we fake-doxygenate - dstyles_in = os.path.join(ctx.template_dir, 'doxygen.css') - dstyles_css = os.path.join(ctx.docdir, 'doxygen.css') - shutil.copyfile(dstyles_in, dstyles_css) except: traceback.print_exc() diff --git a/tools/rosdoc/src/rosdoc/doxygenator.py b/tools/rosdoc/src/rosdoc/doxygenator.py index 6bb928ab..7d4a3c44 100644 --- a/tools/rosdoc/src/rosdoc/doxygenator.py +++ b/tools/rosdoc/src/rosdoc/doxygenator.py @@ -49,46 +49,6 @@ external_template = load_tmpl('external.html') header_template = load_tmpl('header.html') footer_template = load_tmpl('footer.html') manifest_template = load_tmpl('manifest.html') -wiki_header_template = load_tmpl('wiki-header.html') - -# routines for including links to msgenator files -def _href(url, text): - return '%(text)s'%locals() -def msg_link(msg): - return _href('msg/%(msg)s.html'%locals(), msg) -def srv_link(srv): - return _href('srv/%(srv)s.html'%locals(), srv) - -# table of msgs/srvs provided by package. this is a duplicate of the -# PackageHeader.py code in the roswiki Moin -def msgenator_html(msgs, srvs): - # include table of msgs/srvs - msg_str = '' - if msgs or srvs: - if msgs and srvs: - msg_str += '

ROS Message and Service Types

' - elif msgs: - msg_str += '

ROS Message Types

\n' - elif srvs: - msg_str += '

ROS Service Types

\n' - msg_str += '\n\n' - if msgs: - if srvs: - msg_str += '\n' - if srvs: - if msgs: - msg_str += '\n' - msg_str += '' - if msgs: - msg_str += '\n' - if srvs: - msg_str += '\n' - msg_str += '
ROS Message TypesROS Service Types
\n'+\ - '
\n'.join([msg_link(m) for m in msgs])+\ - '
\n'+\ - '
\n'.join([srv_link(s) for s in srvs])+\ - '
' - return msg_str # other templates @@ -117,14 +77,14 @@ def generate_msg_srv_includes(package, tmp, to_delete): html_file.write(_msg_srv_tmpl(ext, type_, f.read())) ## @param package str: package name +## @param rd_config dict: rosdoc configuration parameters for this doxygen build ## @param m Manifest : package manifest -## @param docdir str: directory to store documentation in -def create_package_template(package, m, path, docdir, header_filename, footer_filename): - #replace vars in the template file to point to package we are documenting - if not os.path.exists(docdir): - os.mkdir(docdir) - - #TODO: replace with general purpose key/value parser/substitution to enable feature +## @param html_dir str: directory to store doxygen files +def create_package_template(package, rd_config, m, path, html_dir, + header_filename, footer_filename): + # TODO: allow rd_config to specify excludes and whatnot + + # TODO: replace with general purpose key/value parser/substitution to enable feature # determine the value of overridable keys file_patterns = '*.c *.cpp *.h *.cc *.hh *.py *.dox' @@ -133,16 +93,22 @@ def create_package_template(package, m, path, docdir, header_filename, footer_fi for e in m.get_export('doxygen', 'excludes'): # prepend the packages path excludes = '%s/%s'%(path, e) + # rd_config wins + if rd_config and 'excludes' in rd_config: + excludes = rd_config['excludes'] + # last one wins for e in m.get_export('doxygen', 'file-patterns'): file_patterns = e + # rd_config wins + if rd_config and 'file_patterns' in rd_config: + file_patterns = rd_config['file_patterns'] - html_output = html_path(package, docdir) - vars = { '$INPUT': path, '$PROJECT_NAME': package, '$EXCLUDE_PROP': excludes, '$FILE_PATTERNS': file_patterns, + '$HTML_OUTPUT': os.path.abspath(html_dir), '$HTML_HEADER': header_filename, '$HTML_FOOTER': footer_filename, - '$OUTPUT_DIRECTORY': os.path.join(docdir, package), '$HTML_OUTPUT': html_output} + '$OUTPUT_DIRECTORY': html_dir} return instantiate_template(doxy_template, vars) ## Processes manifest for package and then generates templates for @@ -153,7 +119,7 @@ def create_package_template(package, m, path, docdir, header_filename, footer_fi ## @return (str, str, str): header, footer, manifest def load_manifest_vars(ctx, package, path, docdir, m): author = license = dependencies = description = usedby = status = notes = li_vc = li_url = brief = '' - wiki_url = 'http://pr.willowgarage.com/wiki/%s'%package + wiki_url = 'http://ros.org/wiki/%s'%package project_link = '%s'%(wiki_url, package) if m: license = m.license or '' @@ -187,9 +153,6 @@ def load_manifest_vars(ctx, package, path, docdir, m): # include links to msgs/srvs msgs = roslib.msgs.list_msg_types(package, False) srvs = roslib.srvs.list_srv_types(package, False) - msgen = msgenator_html(msgs, srvs) - if msgen is None: - raise Exception('msgen is none') return {'$package': package, '$projectlink': project_link, '$license': license, @@ -197,7 +160,7 @@ def load_manifest_vars(ctx, package, path, docdir, m): '$description': description, '$brief': brief, '$author': author, '$status':status, '$notes':notes, '$li_vc': li_vc, '$li_url': li_url, - '$msgenator': msgen} + } ## utility to write string data to files and handle unicode def _write_to_file(f, tmpl): @@ -228,10 +191,10 @@ If you are on Ubuntu/Debian, you can install doxygen by typing: """ sys.exit(1) -def run_rxdeps(package, dir): - if 1: return +#TODO: move elsewhere +def run_rxdeps(package, pkg_doc_dir): try: - command = ['rxdeps', '-s', '--target=%s'%package, '--cluster', '-o', os.path.join(dir, package, 'html', '%s_deps.pdf'%package)] + command = ['rxdeps', '-s', '--target=%s'%package, '--cluster', '-o', os.path.join(pkg_doc_dir, '%s_deps.pdf'%package)] print "rxdeping %s [%s]"%(package, ' '.join(command)) Popen(command, stdout=PIPE).communicate() except OSError, (errno, strerr): @@ -242,6 +205,10 @@ Package dependency tree links will not work properly. ## Main entrypoint into creating doxygen files ## @return [str]: list of packages that were successfully generated def generate_doxygen(ctx, quiet=False): + + #TODO: move external generator into its own generator + #TODO: move rxdeps into its own generator + # setup temp directory tmp = 'tmp' if not os.path.exists(tmp): @@ -255,22 +222,47 @@ def generate_doxygen(ctx, quiet=False): # list of packages that we are documenting doc_packages = ctx.doc_packages external_docs = ctx.external_docs + rd_configs = ctx.rd_configs manifests = ctx.manifests - tmpls = [header_template, footer_template, manifest_template, wiki_header_template] + tmpls = [header_template, footer_template, manifest_template] try: for package, path in packages.iteritems(): - if not package in doc_packages: + if not package in doc_packages or not ctx.has_builder(package, 'doxygen'): continue - html_dir = os.path.join(dir, package, 'html') - # have to makedirs for external packages - if not os.path.exists(html_dir): - os.makedirs(html_dir) + + # the logic for the doxygen builder is different from + # others as doxygen is the default builder if no config is + # declared + rd_config = rd_configs.get(package, None) + if rd_config: + # currently only allow one doxygen build per package. This is not inherent, it + # just requires rewriting higher-level logic + rd_config = [d for d in ctx.rd_configs[package] if d['builder'] == 'doxygen'][0] + + # Configuration (all are optional) + # + # name: Documentation set name (e.g. C++ API) + # output_dir: Directory to store files (default '.') + # file-patterns: override FILE_PATTERNS + # excludes: override EXCLUDES + + # doxygenator currently does some non-doxygen work. + # pkg_doc_dir is the pointer to the directory for these non-doxygen + # tools. html_dir is the path for doxygen + pkg_doc_dir = html_path(package, ctx.docdir) + # compute the html directory for doxygen + html_dir = html_path(package, ctx.docdir) + if rd_config and 'output_dir' in rd_config: + html_dir = os.path.join(html_dir, rd_config['output_dir']) + + # have to makedirs for external packages + if not os.path.exists(pkg_doc_dir): + os.makedirs(pkg_doc_dir) + files = [] try: - #TODO: cleanup the temporary files - header_file = tempfile.NamedTemporaryFile('w+') footer_file = tempfile.NamedTemporaryFile('w+') doxygen_file = tempfile.NamedTemporaryFile('w+') @@ -285,11 +277,14 @@ def generate_doxygen(ctx, quiet=False): # - instantiate the templates manifest_ = manifests[package] if package in manifests else None vars = load_manifest_vars(ctx, package, path, dir, manifest_) - header, footer, manifest_html, wiki_header = [instantiate_template(t, vars) for t in tmpls] + header, footer, manifest_html = [instantiate_template(t, vars) for t in tmpls] - run_rxdeps(package, dir) + run_rxdeps(package, pkg_doc_dir) if package not in external_docs: - doxy = create_package_template(package, manifest_, path, dir, header_file.name, footer_file.name) + doxy = \ + create_package_template(package, rd_config, manifest_, + path, html_dir, + header_file.name, footer_file.name) for f, tmpl in zip(files, [header, footer, manifest_html, doxy]): _write_to_file(f, tmpl) # doxygenate @@ -300,18 +295,27 @@ def generate_doxygen(ctx, quiet=False): # it is time consuming for packages that provide their own docs external_link = ctx.external_docs[package] + + # Override mainpage title if 'name' is in config + title = 'Main Page' + if rd_config: + title = rd_config.get('name', title) vars = { '$package': package, '$external_link': external_link, '$header': header, '$footer': footer, '$manifest': manifest_html, # doxygen vars '$relpath$': '../../', - '$title': package+': Main Page', + '$title': package+': '+title, } - with open(os.path.join(html_dir, 'index.html'), 'w') as ext_html_file: - _write_to_file(ext_html_file, instantiate_template(external_template, vars)) - with open(os.path.join(html_dir, 'wiki_header.html'), 'w') as wiki_header_file: - _write_to_file(wiki_header_file, wiki_header) + with open(os.path.join(pkg_doc_dir, 'index.html'), 'w') as ext_html_file: + _write_to_file(ext_html_file, instantiate_template(external_template, vars)) + + # support files (stylesheets) + import shutil + dstyles_in = os.path.join(ctx.template_dir, 'doxygen.css') + dstyles_css = os.path.join(html_dir, 'doxygen.css') + shutil.copyfile(dstyles_in, dstyles_css) success.append(package) finally: diff --git a/tools/rosdoc/src/rosdoc/epyenator.py b/tools/rosdoc/src/rosdoc/epyenator.py index 81379d23..13ce6486 100644 --- a/tools/rosdoc/src/rosdoc/epyenator.py +++ b/tools/rosdoc/src/rosdoc/epyenator.py @@ -37,19 +37,32 @@ from __future__ import with_statement import os, sys from subprocess import Popen, PIPE -## Main entrypoint into creating Eepydoc documentation +from rosdoc.rdcore import * + +## Main entrypoint into creating Epydoc documentation ## @return [str]: list of packages that were successfully generated def generate_epydoc(ctx): success = [] for package, path in ctx.packages.iteritems(): - if package in ctx.doc_packages and ctx.should_document(package): - builder = ctx.builder[package] - if builder != 'epydoc': - continue + if package in ctx.doc_packages and ctx.should_document(package) \ + and ctx.has_builder(package, 'epydoc'): + + # currently only allow one epydoc build per package. This + # is not inherent, it just requires rewriting higher-level + # logic + rd_config = [d for d in ctx.rd_configs[package] if d['builder'] == 'epydoc'][0] + + # Configuration Properties (all optional): + # + # output_dir: directory_name (default: '.') + # name: Documentation Set Name (default: Python API) try: - html_dir = os.path.join(ctx.docdir, package, 'html') + html_dir = html_path(package, ctx.docdir) + if 'output_dir' in rd_config: + html_dir = os.path.join(html_dir, rd_config['output_dir']) if not os.path.isdir(html_dir): os.makedirs(html_dir) + command = ['epydoc', '--html', package, '-o', html_dir] # determine the python path of the package @@ -64,5 +77,5 @@ def generate_epydoc(ctx): Popen(command, stdout=PIPE, env=env).communicate() success.append(package) except Exception, e: - print >> sys.stderr, "Unable to generate eepydoc for [%s]. This is probably because eepydoc is not installed.\nThe exact error is:\n\t%s"%(package, str(e)) + print >> sys.stderr, "Unable to generate epydoc for [%s]. This is probably because epydoc is not installed.\nThe exact error is:\n\t%s"%(package, str(e)) return success diff --git a/tools/rosdoc/src/rosdoc/landing_page.py b/tools/rosdoc/src/rosdoc/landing_page.py new file mode 100644 index 00000000..bf102000 --- /dev/null +++ b/tools/rosdoc/src/rosdoc/landing_page.py @@ -0,0 +1,130 @@ +#!/usr/bin/env python +# Software License Agreement (BSD License) +# +# Copyright (c) 2008, Willow Garage, Inc. +# 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. +# * Neither the name of Willow Garage, Inc. nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# 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. +# + +from __future__ import with_statement + +import os, sys +import time + +from subprocess import Popen, PIPE + +import roslib.msgs +import roslib.srvs +from rosdoc.rdcore import * + +def _href(location, text): + return '%(text)s'%locals() + +def link_name(rd_config): + if 'name' in rd_config: + n = rd_config['name'] + else: + if rd_config['builder'] == 'doxygen': + return 'C++ API' + elif rd_config['builder'] in ['epydoc', 'sphinx']: + return 'Python API' + else: + return builder + return n + +def generate_links(ctx, package, base_dir, rd_configs): + output_dirs = [c.get('output_dir', None) for c in rd_configs] + # filter out empties + output_dirs = [d for d in output_dirs if d and d != '.'] + + # length check. if these are unequal, cannot generate landing + # page. this is often true if the config is merely generating + # local + if len(output_dirs) != len(rd_configs): + return None + + links = [] + for c, d in zip(rd_configs, output_dirs): + links.append(_href(d, link_name(c))) + + msgs = roslib.msgs.list_msg_types(package, False) + srvs = roslib.srvs.list_srv_types(package, False) + if msgs or srvs: + if msgs and srvs: + title = 'msg/srv API' + elif msgs and not srvs: + title = 'msg API' + elif srvs and not msgs: + title = 'srv API' + #TODO: this shouldn't be hardcoded to index-msg.html + links.append(_href('index-msg.html', title)) + + url = ctx.manifests[package].url + if url: + links.append(_href(url, '%s Package Documentation'%package)) + return links + +## Generate landing page in the event that there are multiple documentation sets +## @return [str]: list of packages for which there are landing pages generated +def generate_landing_page(ctx): + success = [] + template = load_tmpl('landing.template') + for package, path in ctx.packages.iteritems(): + if package in ctx.doc_packages and ctx.should_document(package) and \ + package in ctx.rd_configs: + + rd_configs = ctx.rd_configs[package] + links = generate_links(ctx, package, ctx.docdir, rd_configs) + # if links is empty, it means that the rd_configs builds + # to the base directory and no landing page is required + # (or it means that the config is corrupt) + if not links: + print "ignoring landing page for", package + return + + try: + html_dir = html_path(package, ctx.docdir) + if not os.path.isdir(html_dir): + os.makedirs(html_dir) + + links_html = '\n'.join(['
  • %s
  • '%l for l in links]) + date = str(time.strftime('%a, %d %b %Y %H:%M:%S')) + vars = { + '$package': package, + '$links': links_html, + '$date': date, + } + + print "generating landing page", html_dir + with open(os.path.join(html_dir, 'index.html'), 'w') as f: + f.write(instantiate_template(template, vars)) + success.append(package) + except Exception, e: + print >> sys.stderr, "Unable to generate landing_page for [%s]:\n\t%s"%(package, str(e)) + return success diff --git a/tools/rosdoc/src/rosdoc/rdcore.py b/tools/rosdoc/src/rosdoc/rdcore.py index 5153236b..5f8c3aac 100644 --- a/tools/rosdoc/src/rosdoc/rdcore.py +++ b/tools/rosdoc/src/rosdoc/rdcore.py @@ -32,6 +32,8 @@ # # Revision $Id: doxyutil.py 3727 2009-02-06 22:42:26Z sfkwc $ +from __future__ import with_statement + import os import sys from subprocess import Popen, PIPE @@ -63,10 +65,23 @@ class RosdocContext(object): self.stacks = {} self.external_docs = {} self.manifests = {} - self.builder = {} - self.stack_manifests = {} + self.stack_manifests = {} + # advanced per-package config + self.rd_configs = {} self.template_dir = None + + ## @return: True if package is configured to use builder. NOTE: if + ## there is no config, package is assumed to define a doxygen + ## builder + def has_builder(self, package, builder): + rd_config = self.rd_configs.get(package, None) + if not rd_config: + return builder == 'doxygen' + try: + return len([d for d in rd_config if d['builder'] == builder]) > 0 + except KeyError: + print >> sys.stderr, "config file for [%s] is invalid, missing required 'builder' key"%package ## @return bool True if \a package should be document def should_document(self, package): @@ -107,9 +122,9 @@ class RosdocContext(object): ## Crawl manifest.xml dependencies def _crawl_deps(self): - builder = self.builder external_docs = self.external_docs manifests = self.manifests + rd_configs = self.rd_configs stacks = self.stacks = {} @@ -130,22 +145,29 @@ class RosdocContext(object): try: manifests[package] = m = roslib.manifest.parse_file(f) + #NOTE: the behavior is undefined if the users uses + #both config and export properties directly + # #1650 for backwards compatibility, we ready the old # 'doxymaker' tag, which is deprecated - - # this is a loop but we only accept one value + # - this is a loop but we only accept one value for e in m.get_export('doxymaker', 'external'): external_docs[package] = e for e in m.get_export('rosdoc', 'external'): external_docs[package] = e - builder[package] = 'doxygen' - for e in m.get_export('rosdoc', 'builder'): - builder[package] = e.lower() - if builder[package] not in ['epydoc', 'doxygen', 'sphinx']: - print >> sys.stderr, "ERROR: unknown builder [%s]. Using doxygen instead"%builder[package] - builder[package] = 'doxygen' + # load in any external config files + for e in m.get_export('rosdoc', 'config'): + import yaml + try: + e = e.replace('${prefix}', path) + config_p = os.path.join(path, e) + with open(config_p, 'r') as config_f: + rd_configs[package] = yaml.load(config_f) + except Exception, e: + print >> sys.stderr, "ERROR: unable to load rosdoc config file [%s]: %s"%(config_p, str(e)) + except: print >> sys.stderr, "WARN: Package '%s' does not have a valid manifest.xml file, manifest information will not be included in docs"%package diff --git a/tools/rosdoc/src/rosdoc/sphinxenator.py b/tools/rosdoc/src/rosdoc/sphinxenator.py index 3b787dfc..e2536c5c 100644 --- a/tools/rosdoc/src/rosdoc/sphinxenator.py +++ b/tools/rosdoc/src/rosdoc/sphinxenator.py @@ -43,11 +43,18 @@ from subprocess import Popen, PIPE def generate_sphinx(ctx): success = [] for package, path in ctx.packages.iteritems(): - if package in ctx.doc_packages and ctx.should_document(package): + if package in ctx.doc_packages and ctx.should_document(package) and \ + ctx.has_builder(package, 'sphinx'): try: - builder = ctx.builder[package] - if builder != 'sphinx': - continue + + # currently only allow one sphinx build per package. This + # is not inherent, it just requires rewriting higher-level + # logic + rd_config = [d for d in ctx.rd_configs[package] if d['builder'] == 'sphinx'][0] + + # rd_config is currently a flag. In the future, I imagine it pointing + # to the location of index.rst, among other things + if os.access(os.path.join(path, "index.rst"), os.R_OK): oldcwd = os.getcwd() os.chdir(path) diff --git a/tools/rosdoc/templates/doxy.template b/tools/rosdoc/templates/doxy.template index 08c4ed56..d0d79a98 100644 --- a/tools/rosdoc/templates/doxy.template +++ b/tools/rosdoc/templates/doxy.template @@ -106,7 +106,7 @@ IGNORE_PREFIX = # configuration options related to the HTML output #--------------------------------------------------------------------------- GENERATE_HTML = YES -HTML_OUTPUT = html +HTML_OUTPUT = $HTML_OUTPUT HTML_FILE_EXTENSION = .html HTML_HEADER = $HTML_HEADER HTML_FOOTER = $HTML_FOOTER @@ -125,7 +125,7 @@ TREEVIEW_WIDTH = 250 #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- -GENERATE_LATEX = YES +GENERATE_LATEX = NO LATEX_OUTPUT = latex LATEX_CMD_NAME = latex MAKEINDEX_CMD_NAME = makeindex diff --git a/tools/rosdoc/templates/landing.template b/tools/rosdoc/templates/landing.template new file mode 100644 index 00000000..c929ad50 --- /dev/null +++ b/tools/rosdoc/templates/landing.template @@ -0,0 +1,17 @@ + + +$package Documentation + + + + + +

    $package API Documentation

    + + +$links + + + + + diff --git a/tools/rosdoc/templates/manifest.html b/tools/rosdoc/templates/manifest.html index 35e8a263..c6e87451 100644 --- a/tools/rosdoc/templates/manifest.html +++ b/tools/rosdoc/templates/manifest.html @@ -10,8 +10,5 @@ $li_url $li_vc
  • Dependency Tree
  • - -$msgenator -

    diff --git a/tools/rosservice/manifest.xml b/tools/rosservice/manifest.xml index c170579c..caaf339d 100644 --- a/tools/rosservice/manifest.xml +++ b/tools/rosservice/manifest.xml @@ -13,7 +13,7 @@ rosservice contains the rosservice command-line tool for listing and querying RO - + diff --git a/tools/rosservice/rosdoc.yaml b/tools/rosservice/rosdoc.yaml new file mode 100644 index 00000000..0bdea97f --- /dev/null +++ b/tools/rosservice/rosdoc.yaml @@ -0,0 +1 @@ + - builder: epydoc diff --git a/tools/rostopic/manifest.xml b/tools/rostopic/manifest.xml index e1ec6f2d..53a4f84d 100644 --- a/tools/rostopic/manifest.xml +++ b/tools/rostopic/manifest.xml @@ -21,7 +21,7 @@ internal-use only as its API is not stable. - + diff --git a/tools/rostopic/rosdoc.yaml b/tools/rostopic/rosdoc.yaml new file mode 100644 index 00000000..0bdea97f --- /dev/null +++ b/tools/rostopic/rosdoc.yaml @@ -0,0 +1 @@ + - builder: epydoc