Newer
Older
#
# The documentation generation process is tightly integrated with the
# scons build framework:
#
# * SCons analyzes the Doxyfile's to find all the documentation
# dependencies. This happens in the doxygen builder in
# senfscons/Doxygen.py.
#
# * the doclib/doxy-header.html and/or doclib/doxy-footer.html files
# are regenerated
#
# * If any documentation is out-of-date with respect to it's source
# files, the documentation is regenerated.
#
# * To fix some link errors, the additional 'linklint' and 'fixlinks'
# targets are used
#
#
# 1. Scanning the Doxyfile's
#
# The doxygen builder scans all documentation source files which have
# the text 'doxyfile' in any case in their name. It understands
# @INCLUDE directives and will find all the dependencies of the
# documentation:
#
# * All the source files as selected by INPUT, INPUT_PATTERN,
# RECURSIVE and so on.
#
# * Any referenced tag-files
#
# * Documentation header and/or footer
#
# * The INPUT_FILTER program
#
# * Any included doxygen configuration files
#
#
# 2. Regenerating header and/or footer
#
# If needed, the doxy-header.html and/or doxy-footer.html file will be
# regenerated. The header and/or footer are generated from templates
# using a simple python based templating system called yaptu which is
# included in doclib/.
#
#
# 3. Calling doxygen
#
# The doxygen call itself is quite complex since there is some pre-
# and post-processing going on. We can separate this step into two
# steps
#
# * Building prerequisites (e.g. images)
#
# * The processing done by the Doxygen builder and doclib/doxygen.sh
#
#
# 3.1. Building prerequisites
#
# The prerequisites are images referenced by the documentation. These
# images are mostly generated using the Dia2Png builder.
#
#
# 3.2. The main doxygen build (Doxygen builder)
#
# The Doxygen builder will call the doxygen command to build the
# documentation.
#
# The doxygen command is configured as 'doclib/doxygen.sh' which
# does some additional processing in addition to calling doxygen
# proper
#
# * it sets environment variables depending on command line arguments.
# These variables are then used in the Doxyfile's
#
# * after doxygen is finished, 'installdox' is called to resolve
# tag file references.
#
# * the HTML documentation is post-processed using some sed, tidy, and
# an XSLT template
#
# * a generated tag file is post-processed using an XSLT template
#
# (see doclib/doxygen.sh for more information). The Doxygen
# configuration is set up such, that
#
# * doxygen calls 'doclib/filter.pl' on each source file. This filter
# will strip excess whitespace from the beginning of lines in
# '\code' and '<pre>' blocks. Additionally it will expand all tabs,
# tab width is 8 spaces (there should be no tabs in the source but
# ...)
# * doxygen calls 'doclib/dot' to generate the 'dot' images.
#
# * 'doclib/dot' calls 'doclib/dot-munge.pl' on the .dot
# files. dot-munge.pl changes the font and font-size and adds
# line-breaks to long labels
#
# * 'doclib/dot' calls the real dot binary. If the resulting image is
# more than 800 pixels wide, dot is called again, this time using
# the oposite rank direction (top-bottom vs. left-right). The image
# with the smaller width is selected and returned.
#
#
#
# After the documentation has been generated, additional calls first
# to the 'linklint' and then to the 'fixlinks' target will try to fix
# broken links generated by doxygen. First, 'linklint' will call the
# linklint tool to check for broken links in the documentation.
#
# 'fixlinks' is then called which calls 'doclib/fixlinks.py' which
# scans *all* html files, builds an index of all (unique) anchors and
# then fixes the url part of all links with correct anchor but bad
# file name.
#
import SENFSCons, datetime, os
###########################################################################
import yaptu
def modules():
# Naja ... etwas rumgehackt aber was solls ...
global EXTRA_MODULES
mods = {}
for module in env.Alias('all_docs')[0].sources:
if module.name != 'html.stamp' : continue
mods[module.dir.dir.dir.abspath] = [ module.dir.dir.dir.name,
module.dir.abspath[pathbase:],
0 ]
rv = []
keys = mods.keys()
keys.sort()
for mod in keys:
i = 0
while i < len(rv):
level = mods[rv[i]][2] + 1
i += 1
while i < len(rv) and mods[rv[i]][2] >= level:
i += 1
rv[i:i] = [ mod ]
mods[mod][2] = level
break
i += 1
if i == len(rv):
rv.append(mod)
for mod in keys:
if mods[mod][2] == 0:
mods[mod][0] = 'lib' + mods[mod][0]
n = 0
for name,path in EXTRA_MODULES:
path = env.Dir(path).dir.dir.abspath
i = 0
while i < len(rv):
if rv[i] == path:
mods[rv[i]][0] = name
m = 1
while i+m < len(rv) and mods[rv[i+m]][2] > mods[rv[i]][2]:
m += 1
rv[n:n] = rv[i:i+m]
rv[i+m:i+2*m] = []
i += m
n += m
else:
i += 1
return ( tuple(mods[mod]) for mod in rv )
def indices():
ix = len(env.Dir('#').abspath)+1
return [ doc.dir.abspath[ix:]
for doc in env.Alias('all_docs')[0].sources
if doc.name == "search.idx" ]
def writeTemplate(target = None, source = None, env = None):
file(target[0].abspath,"w").write(processTemplate(env))
def processTemplate(env):
return yaptu.process(str(env['TEMPLATE']), globals(), env.Dictionary())
writeTemplate = env.Action(writeTemplate, varlist = [ 'TEMPLATE' ])
###########################################################################
# Extra documentation modules which are handled (named) different from
# library modules
EXTRA_MODULES = [
('Overview', '#/doc/html'),
('Examples', '#/Examples/doc/html'),
HEADER = """<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>$title</title>
<link href="@TOPDIR@/doc/html/doxygen.css" rel="stylesheet" type="text/css">
<link href="@TOPDIR@/doclib/senf.css" rel="stylesheet" type="text/css">
<style type="text/css">
g0dil
committed
div.tabs li.$projectname a { background-color: #EDE497; }
</style>
</head>
<body>
<div id="head">
<div id="title">
<div id="title2">
<div id="search">
<form action="@TOPDIR@/doclib/search.php" method="get">
Search: <input type="text" name="query" size="20" accesskey="s"/>
</form>
</div>
<h1>SENF Extensible Network Framework</h1>
</div>
<div id="subtitle">
<ul>
<li><a href="@TOPDIR@/doc/html/index.html">Home</a></li>
<li><a class="ext" href="http://satext.fokus.fraunhofer.de/senf/debian">Download</a></li>
<li><a class="ext" href="http://openfacts2.berlios.de/wikien/index.php/BerliosProject:SENF_Network_Framework">Wiki</a></li>
<li><a class="ext" href="http://developer.berlios.de/projects/senf">BerliOS</a></li>
<li><a class="ext" href="http://svn.berlios.de/wsvn/senf/?op=log&rev=0&sc=0&isdir=1">ChangeLog</a></li>
<li><a class="ext" href="http://svn.berlios.de/viewcvs/senf/trunk/">Browse SVN</a></li>
<li><a class="ext" href="http://developer.berlios.de/bugs/?group_id=7489">Bug Tracker</a></li>
</ul>
</div>
</div>
<div id="content1">
<div id="content2">
<div class="tabs menu">
<ul>
{{ for name, path, level in modules():
<li class="${name} level${level}"><a href="@TOPDIR@/${path}/index.html">${name}</a></li>
g0dil
committed
<li class="glossary level0"><a href="@TOPDIR@/doc/html/glossary.html">Glossary</a></li>
</ul>
</div>"""
FOOTER = """<hr style="width:0px;border:none;clear:both;margin:0;padding:0" />
</div>
</div>
<div id="footer">
<span>
<a href="mailto:senf-dev@lists.berlios.de">Contact: senf-dev@lists.berlios.de</a> |
Copyright © 2006 Fraunhofer Gesellschaft, SatCom, Stefan Bund
</span>
</div>
</body></html>"""
SEARCH_PHP="""
<?php include 'search_functions.php'; ?>
<?php search(); ?>"""
SEARCH_PATHS_PHP="""<?php
function paths() {
return array(
"../${index}/",
}}
);
}
?>"""
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
env.Append( ENV = {
'TODAY' : str(datetime.date.today()),
'TEXINPUTS' : os.environ.get('TEXINPUTS',env.Dir('#/doclib').abspath + ':'),
'DOXYGEN' : env.get('DOXYGEN', 'doxygen'),
})
env.Replace(
ALL_TAGFILES = [],
DOXYGENCOM = "doclib/doxygen.sh $DOXYOPTS $SOURCE",
)
SENFSCons.PhonyTarget(env, 'linklint', [
'rm -rf linklint',
'linklint -doc linklint -limit 99999999 `find -type d -name html -printf "/%P/@ "`',
'[ ! -r linklint/errorX.html ] || python doclib/linklint_addnames.py <linklint/errorX.html >linklint/errorX.html.new',
'[ ! -r linklint/errorX.html.new ] || mv linklint/errorX.html.new linklint/errorX.html',
'[ ! -r linklint/errorAX.html ] || python doclib/linklint_addnames.py <linklint/errorAX.html >linklint/errorAX.html.new',
'[ ! -r linklint/errorAX.html.new ] || mv linklint/errorAX.html.new linklint/errorAX.html',
'echo -e "\\nLokal link check results: linklint/index.html\\nRemote link check results: linklint/urlindex.html\\n"',
])
env.Clean('all', env.Dir('linklint'))
SENFSCons.PhonyTarget(env, 'fixlinks', [
'python doclib/fix-links.py -v -s .svn -s linklint -s debian linklint/errorX.txt linklint/errorAX.txt',
])
header = env.Command('doxy-header.html', 'SConscript', writeTemplate,
TEMPLATE = Literal(HEADER),
TITLE = "Documentation and API reference")
env.Depends(header, env.Value(repr(list(modules()))))
footer = env.Command('doxy-footer.html', 'SConscript', writeTemplate,
TEMPLATE = Literal(FOOTER))
env.Alias('all_docs',
env.Command('search.php', [ 'html-munge.xsl', 'SConscript' ],
[ writeTemplate,
'xsltproc --nonet --html --stringparam topdir .. -o - $SOURCE $TARGET 2>/dev/null'
+ "| sed"
+ r" -e 's/\[\[/<?/g' -e 's/\]\]/?>/g'"
+ r" -e 's/\$$projectname/Overview/g'"
+ r" -e 's/\$$title/Search results/g'"
'mv ${TARGET}.tmp ${TARGET}' ],
TEMPLATE = Literal(HEADER
+ SEARCH_PHP.replace('<?','[[').replace('?>',']]')
+ FOOTER),
TITLE = "Search results"))
env.Alias('all_docs',
env.Command('search_paths.php', 'SConscript', writeTemplate,
TEMPLATE = Literal(SEARCH_PATHS_PHP)))
env.Alias('install_all',
env.Install( '$DOCINSTALLDIR/doclib', [ 'favicon.ico',
'logo-head.png',
'search.php',
'search_functions.php',
'search_paths.php',
'senf.css' ] ))
env.Clean('all', 'doxy-header.html') # I should not need this but I do ...
env.Clean('all_docs', 'doxy-header.html') # I should not need this but I do ...