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
This commit is contained in:
parent
3e6fc574b6
commit
fcda5f921e
|
@ -7,9 +7,10 @@
|
|||
<author>Ken Conley/kwc@willowgarage.com, Morgan Quigley/mquigley@cs.stanford.edu</author>
|
||||
<license>BSD</license>
|
||||
<review status="API cleared" notes=""/>
|
||||
<url>http://pr.willowgarage.com/wiki/roslib</url>
|
||||
<url>http://ros.org/wiki/roslib</url>
|
||||
<export>
|
||||
<cpp cflags="-I${prefix}/msg/cpp -I${prefix}/include `rosboost-cfg --cflags`" lflags="-Wl,-rpath,${prefix}/lib -L${prefix}/lib -lroslib"/>
|
||||
<rosdoc config="${prefix}/rosdoc.yaml" />
|
||||
</export>
|
||||
<depend package="genmsg_cpp"/>
|
||||
|
||||
|
|
|
@ -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'
|
|
@ -31,7 +31,7 @@
|
|||
<depend package="roslang"/>
|
||||
<export>
|
||||
<roslang cmake="${prefix}/cmake/rospy.cmake"/>
|
||||
<rosdoc builder="epydoc"/>
|
||||
<rosdoc config="rosdoc.yaml"/>
|
||||
</export>
|
||||
</package>
|
||||
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
- builder: epydoc
|
|
@ -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()
|
||||
|
|
|
@ -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 '<a href="%(url)s">%(text)s</a>'%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 += '<h2>ROS Message and Service Types</h2>'
|
||||
elif msgs:
|
||||
msg_str += '<h2>ROS Message Types</h2>\n'
|
||||
elif srvs:
|
||||
msg_str += '<h2>ROS Service Types</h2>\n'
|
||||
msg_str += '<table border="0">\n<tr>\n'
|
||||
if msgs:
|
||||
if srvs:
|
||||
msg_str += '<th>ROS Message Types</th>\n'
|
||||
if srvs:
|
||||
if msgs:
|
||||
msg_str += '<th>ROS Service Types</th>\n'
|
||||
msg_str += '</tr><tr>'
|
||||
if msgs:
|
||||
msg_str += '<td valign="top">\n'+\
|
||||
'<br />\n'.join([msg_link(m) for m in msgs])+\
|
||||
'</td>\n'
|
||||
if srvs:
|
||||
msg_str += '<td valign="top">\n'+\
|
||||
'<br />\n'.join([srv_link(s) for s in srvs])+\
|
||||
'</td>\n'
|
||||
msg_str += '</tr></table>'
|
||||
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 <export><doxygen key="foo" val="var"></export> 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 <export><doxygen key="foo" val="var"></export> 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 = '<a href="%s">%s</a>'%(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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 '<a href="%(location)s">%(text)s</a>'%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(['<li class="landing-li">%s</li>'%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
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>$package Documentation</title>
|
||||
<link type="text/css" rel="stylesheet" href="../../../styles.css" />
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
||||
<h1>$package API Documentation</h1>
|
||||
|
||||
|
||||
$links
|
||||
|
||||
|
||||
<p class="landing-footer"><small>autogenerated on $date</small></p>
|
||||
</body>
|
||||
</html>
|
|
@ -10,8 +10,5 @@ $li_url
|
|||
$li_vc
|
||||
<li><a href="$package_deps.pdf">Dependency Tree</a></li>
|
||||
</ul>
|
||||
|
||||
$msgenator
|
||||
|
||||
</p>
|
||||
</div>
|
||||
|
|
|
@ -13,7 +13,7 @@ rosservice contains the rosservice command-line tool for listing and querying RO
|
|||
<depend package="roslib"/>
|
||||
|
||||
<export>
|
||||
<rosdoc builder="epydoc"/>
|
||||
<rosdoc config="rosdoc.yaml"/>
|
||||
</export>
|
||||
|
||||
</package>
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
- builder: epydoc
|
|
@ -21,7 +21,7 @@ internal-use only as its API is not stable.
|
|||
<depend package="rosrecord"/>
|
||||
|
||||
<export>
|
||||
<rosdoc builder="epydoc"/>
|
||||
<rosdoc config="rosdoc.yaml"/>
|
||||
</export>
|
||||
|
||||
</package>
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
- builder: epydoc
|
Loading…
Reference in New Issue