summaryrefslogtreecommitdiff
path: root/doc/SConscript
diff options
context:
space:
mode:
Diffstat (limited to 'doc/SConscript')
-rw-r--r--doc/SConscript530
1 files changed, 530 insertions, 0 deletions
diff --git a/doc/SConscript b/doc/SConscript
new file mode 100644
index 0000000..fd18ef4
--- /dev/null
+++ b/doc/SConscript
@@ -0,0 +1,530 @@
+#
+# SConscript file for building SCons documentation.
+#
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+import os.path
+import re
+import string
+
+Import('build_dir', 'env', 'whereis')
+
+env = env.Clone()
+
+build = os.path.join(build_dir, 'doc')
+
+#
+#
+#
+dist_doc_tar_gz = '$DISTDIR/scons-doc-${VERSION}.tar.gz'
+
+#
+# We'll only try to build text files (for some documents)
+# if lynx is available to do the dump.
+#
+fig2dev = whereis('fig2dev')
+epydoc = whereis('epydoc')
+groff = whereis('groff')
+lynx = whereis('lynx')
+man2html = whereis('man2html')
+jade_original = whereis('jade')
+jade = whereis('openjade') or jade_original
+jadetex = whereis('jadetex')
+pdfjadetex = whereis('pdfjadetex')
+jw = whereis('jw')
+tidy = whereis('tidy')
+
+tar_deps = []
+tar_list = []
+
+entity_re = re.compile(r'<!entity\s+(?:%\s+)?(?:\S+)\s+SYSTEM\s+"([^"]*)">', re.I)
+format_re = re.compile(r'<(?:graphic|imagedata)\s+fileref="([^"]*)"(?:\s+format="([^"]*)")?')
+
+#
+# Find internal dependencies in .xml files:
+#
+# <!entity bground SYSTEM "bground.xml">
+# <graphic fileref="file.jpg">
+# <imagedata fileref="file.jpg">
+#
+# This only finds one per line, and assumes that anything
+# defined as a SYSTEM entity is, in fact, a file included
+# somewhere in the document.
+#
+def scanxml(node, env, target):
+ includes = []
+
+ contents = node.get_text_contents()
+
+ includes.extend(entity_re.findall(contents))
+
+ matches = format_re.findall(contents)
+ for m in matches:
+ file, format = m
+ if format and file[-len(format):] != format:
+ file = file + '.' + format
+ if not os.path.isabs(file):
+ a = []
+ f = file
+ while f:
+ f, tail = os.path.split(f)
+ if tail == 'doc':
+ break
+ a = [tail] + a
+ file = apply(os.path.join, a, {})
+ includes.append(file)
+
+ return includes
+
+s = Scanner(name = 'xml', function = scanxml, skeys = ['.xml', '.mod'])
+
+orig_env = env
+env = orig_env.Clone(SCANNERS = [s],
+ SCONS_PROC_PY = File('#bin/scons-proc.py').rfile(),
+ SCONSOUTPUT_PY = File('#bin/sconsoutput.py').rfile())
+
+# Fetch the list of files in the build engine that contain
+# SCons documentation XML for processing.
+def chop(s): return s[:-1]
+
+# If we ever read doc from __scons_doc__ strings in *.py files again,
+# here's how it's done:
+#manifest_in = File('#src/engine/MANIFEST.in').rstr()
+#manifest_xml_in = File('#src/engine/MANIFEST-xml.in').rstr()
+#scons_doc_files = map(chop, open(manifest_in).readlines() +\
+# open(manifest_xml_in).readlines())
+#scons_doc_files = map(lambda x: '#src/engine/'+x, scons_doc_files)
+#manifest_in = File('#src/engine/MANIFEST.in').rstr()
+
+manifest_xml_in = File('#src/engine/MANIFEST-xml.in').rstr()
+scons_doc_files = map(chop, open(manifest_xml_in).readlines())
+scons_doc_files = map(lambda x: File('#src/engine/'+x).rstr(), scons_doc_files)
+
+if not jw:
+ print "jw not found, skipping building User Guide."
+else:
+ #
+ # Always create a version.xml file containing the version information
+ # for this run. Ignore it for dependency purposes so we don't
+ # rebuild all the docs every time just because the date changes.
+ #
+ date, ver, rev = env.Dictionary('DATE', 'VERSION', 'REVISION')
+ version_xml = File(os.path.join(build, "version.xml"))
+ #version_xml = File("version.xml")
+ verfile = str(version_xml)
+ try:
+ os.unlink(verfile)
+ except OSError:
+ pass # okay if the file didn't exist
+ dir, f = os.path.split(verfile)
+ try:
+ os.makedirs(dir)
+ except OSError:
+ pass # okay if the directory already exists
+ open(verfile, "w").write("""<!--
+THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT.
+-->
+<!ENTITY builddate "%s">
+<!ENTITY buildversion "%s">
+<!ENTITY buildrevision "%s">
+""" % (date, ver, rev))
+
+ builders_gen = os.path.join(build, 'user', 'builders.gen')
+ builders_mod = os.path.join(build, 'user', 'builders.mod')
+ tools_gen = os.path.join(build, 'user', 'tools.gen')
+ tools_mod = os.path.join(build, 'user', 'tools.mod')
+ variables_gen = os.path.join(build, 'user', 'variables.gen')
+ variables_mod = os.path.join(build, 'user', 'variables.mod')
+
+ # We put $( - $) around $SOURCES in the command line below because
+ # the path names will change when a given input file is found in
+ # a repository one run and locally the next, and we don't want
+ # to rebuild documentation just because it's found in one location
+ # vs. the other. The *.gen and *.mod targets will still be dependent
+ # on the list of the files themselves.
+ doc_output_files = [builders_gen, builders_mod,
+ tools_gen, tools_mod,
+ variables_gen, variables_mod]
+ b = env.Command(doc_output_files,
+ scons_doc_files,
+ "$PYTHON $SCONS_PROC_PY --xml -b ${TARGETS[0]},${TARGETS[1]} -t ${TARGETS[2]},${TARGETS[3]} -v ${TARGETS[4]},${TARGETS[5]} $( $SOURCES $)")
+ env.Depends(b, "$SCONS_PROC_PY")
+
+ env.Local(b)
+
+ #
+ # Each document will live in its own subdirectory. List them here
+ # as hash keys, with a hash of the info to control its build.
+ #
+ docs = {
+ 'design' : {
+ 'htmlindex' : 'book1.html',
+ 'ps' : 1,
+ 'pdf' : 1,
+ 'text' : 0,
+ },
+ # This doesn't build on all systems, and the document is old
+ # enough that there's reallyno need to build it every time any
+ # more, so just comment it out for now.
+ #'python10' : {
+ # 'htmlindex' : 't1.html',
+ # 'html' : 1,
+ # 'ps' : 1,
+ # 'pdf' : 0,
+ # 'text' : 0,
+ # 'graphics' : [
+ # 'arch.fig',
+ # 'builder.fig',
+ # 'job-task.fig',
+ # 'node.fig',
+ # 'scanner.fig',
+ # 'sig.fig'
+ # ],
+ #},
+ 'reference' : {
+ 'htmlindex' : 'book1.html',
+ 'html' : 1,
+ 'ps' : 1,
+ 'pdf' : 1,
+ 'text' : 0,
+ },
+ # For whenever (if ever?) we start putting developer guide
+ # information in a printable document instead of the wiki.
+ #'developer' : {
+ # 'htmlindex' : 'book1.html',
+ # 'html' : 1,
+ # 'ps' : 1,
+ # 'pdf' : 1,
+ # 'text' : 0,
+ #},
+ 'user' : {
+ 'htmlindex' : 'book1.html',
+ 'html' : 1,
+ 'ps' : 1,
+ 'pdf' : 1,
+ 'text' : 1,
+ 'graphics' : [
+ 'SCons-win32-install-1.jpg',
+ 'SCons-win32-install-2.jpg',
+ 'SCons-win32-install-3.jpg',
+ 'SCons-win32-install-4.jpg',
+ ],
+ 'sconsoutput' : 1,
+ },
+ }
+
+ #
+ # We have to tell SCons to scan the top-level XML files which
+ # get included by the document XML files in the subdirectories.
+ #
+ manifest = File('MANIFEST').rstr()
+ src_files = map(lambda x: x[:-1], open(manifest).readlines())
+ for s in src_files:
+ base, ext = os.path.splitext(s)
+ if ext in ['.fig', '.jpg']:
+ orig_env.Install(build, s)
+ else:
+ orig_env.SCons_revision(os.path.join(build, s), s)
+ Local(os.path.join(build, s))
+
+ #
+ # For each document, build the document itself in HTML, Postscript,
+ # and PDF formats.
+ #
+ for doc in docs.keys():
+ manifest = File(os.path.join(doc, 'MANIFEST')).rstr()
+ src_files = map(lambda x: x[:-1],
+ open(manifest).readlines())
+ build_doc = docs[doc].get('sconsoutput') and int(ARGUMENTS.get('BUILDDOC', 0))
+ for s in src_files:
+ doc_s = os.path.join(doc, s)
+ build_s = os.path.join(build, doc, s)
+ base, ext = os.path.splitext(doc_s)
+ if ext in ['.fig', '.jpg']:
+ orig_env.InstallAs(build_s, doc_s)
+ else:
+ if build_doc and ext == '.xml':
+ env.Command(doc_s,
+ base + '.in',
+ "$PYTHON $SCONSOUTPUT_PY $SOURCE > $TARGET")
+ orig_env.SCons_revision(build_s, doc_s)
+ Local(build_s)
+
+ main = os.path.join(build, doc, 'main.xml')
+ out = 'main.out'
+
+ # Hard-coding the scons-src path is a bit of a hack. This can
+ # be reworked when a better solution presents itself.
+ scons_src_main = os.path.join(build_dir, 'scons-src', 'doc', main)
+ env.Ignore(scons_src_main, version_xml)
+
+ htmldir = os.path.join(build, 'HTML', 'scons-%s' % doc)
+ htmlindex = os.path.join(htmldir, docs[doc]['htmlindex'])
+ html = os.path.join(build, 'HTML', 'scons-%s.html' % doc)
+ ps = os.path.join(build, 'PS', 'scons-%s.ps' % doc)
+ pdf = os.path.join(build, 'PDF', 'scons-%s.pdf' % doc)
+ text = os.path.join(build, 'TEXT', 'scons-%s.txt' % doc)
+
+ if docs[doc].get('html') and jade:
+ def copy_index_html(target, source, env):
+ # Older versions of DocBook|jw|jade|whatever would
+ # create a book1.html file, while newer versions create
+ # an index.html file (logically enough). The scons.org
+ # web site links expect book1.html, so we're going to
+ # leave the target as is, and run this post-processing
+ # action function to check that the target really did
+ # get created, and if it didn't, copy it from index.html.
+ t = str(target[0])
+ if not os.path.exists(t):
+ i = os.path.join(os.path.split(t)[0], 'index.html')
+ open(t, 'w').write(open(i, 'r').read())
+ return None
+
+ cmds = [
+ Delete("${TARGET.dir}/*.html"),
+ "jw -b html -o ${TARGET.dir} $SOURCES",
+ ]
+ if tidy:
+ cmds.append("tidy -m -q $TARGET || true")
+ cmds.append(Action(copy_index_html))
+ env.Command(htmlindex, File(main), cmds)
+ Local(htmlindex)
+
+ cmds = [
+ Delete("${TARGET.dir}/main.html"),
+ "jw -u -b html -o ${TARGET.dir} $SOURCES",
+ Move("$TARGET", "${TARGET.dir}/main.html"),
+ ]
+ if tidy:
+ cmds.append("tidy -m -q $TARGET || true")
+ env.Command(html, File(main), cmds)
+ Local(html)
+
+ env.Ignore([html, htmlindex], version_xml)
+
+ tar_deps.extend([html, htmlindex])
+ tar_list.extend([html, htmldir])
+
+ for g in docs[doc].get('graphics', []):
+ base, ext = os.path.splitext(g)
+ if ext == '.fig':
+ jpg = base + '.jpg'
+ htmldir_jpg = os.path.join(htmldir, jpg)
+ if fig2dev:
+ fig = os.path.join(build, doc, g)
+ env.Command(htmldir_jpg, fig,
+ "%s -L jpeg -q 100 $SOURCES $TARGET" % fig2dev)
+ else:
+ env.InstallAs(htmldir_jpg, jpg)
+ env.Depends(html, htmldir_jpg)
+ Local(htmldir_jpg)
+ else:
+ src = os.path.join(build, doc, g)
+ Local(env.Install(htmldir, src))
+
+ if docs[doc].get('ps') and jadetex and jade_original:
+ env.Command(ps, main, [
+ Delete("${TARGET.dir}/%s" % out),
+ "jw -b ps -o ${TARGET.dir} -p %s $SOURCES" % jade_original,
+ "mv ${TARGET.dir}/main.ps $TARGET",
+ Delete("${TARGET.dir}/%s" % out),
+ ])
+ Local(ps)
+
+ env.Ignore(ps, version_xml)
+
+ tar_deps.append(ps)
+ tar_list.append(ps)
+
+ for g in docs[doc].get('graphics', []):
+ base, ext = os.path.splitext(g)
+ if ext == '.fig':
+ eps = base + '.eps'
+ build_eps = os.path.join(build, 'PS', eps)
+ if fig2dev:
+ fig = os.path.join(build, doc, g)
+ env.Command(build_eps, fig, "%s -L eps $SOURCES $TARGET" % fig2dev)
+ else:
+ env.InstallAs(build_eps, eps)
+ env.Depends(ps, build_eps)
+ Local(build_eps)
+ else:
+ src = os.path.join(build, doc, g)
+ Local(env.Install(htmldir, src))
+
+ if docs[doc].get('pdf') and pdfjadetex and jade_original:
+ env.Command(pdf, main, [
+ Delete("${TARGET.dir}/%s" % out),
+ "jw -b pdf -o ${TARGET.dir} -p %s $SOURCES" % jade_original,
+ "mv ${TARGET.dir}/main.pdf $TARGET",
+ Delete("${TARGET.dir}/out"),
+ ])
+ Local(pdf)
+
+ env.Ignore(pdf, version_xml)
+
+ tar_deps.append(pdf)
+ tar_list.append(pdf)
+
+ if docs[doc].get('text') and jade and lynx:
+ env.Command(text, html, "lynx -dump ${SOURCE.abspath} > $TARGET")
+ Local(text)
+
+ env.Ignore(text, version_xml)
+
+ tar_deps.append(text)
+ tar_list.append(text)
+
+#
+# Man page(s), in good ol' troff format.
+#
+man_page_list = ['scons.1', 'sconsign.1', 'scons-time.1']
+
+for m in man_page_list:
+ x = orig_env.SCons_revision(os.path.join(build, 'man', m),
+ os.path.join('man', m))
+
+man_i_files = ['builders.man', 'tools.man', 'variables.man']
+
+man_intermediate_files = map(lambda x: os.path.join(build, 'man', x),
+ man_i_files)
+
+cmd = "$PYTHON $SCONS_PROC_PY --man -b ${TARGETS[0]} -t ${TARGETS[1]} -v ${TARGETS[2]} $( $SOURCES $)"
+man_intermediate_files = env.Command(man_intermediate_files,
+ scons_doc_files,
+ cmd)
+env.Depends(man_intermediate_files, "$SCONS_PROC_PY")
+Local(man_intermediate_files)
+
+for man_1 in man_page_list:
+ man, _1 = os.path.splitext(man_1)
+
+ man_1 = os.path.join(build, 'man', man_1)
+
+ if groff:
+ ps = os.path.join(build, 'PS', '%s-man.ps' % man)
+ text = os.path.join(build, 'TEXT', '%s-man.txt' % man)
+
+ b = env.Command(ps, man_1, "( cd ${SOURCES.dir} && groff -man -Tps ${SOURCES.file} ) > $TARGET")
+ Local(ps)
+ env.Depends(b, man_intermediate_files)
+
+ b = env.Command(text, man_1, "( cd ${SOURCES.dir} && groff -man -Tascii ${SOURCES.file} ) > $TARGET")
+ Local(text)
+ env.Depends(b, man_intermediate_files)
+
+ tar_deps.extend([ps, text])
+ tar_list.extend([ps, text])
+
+ if man2html:
+ html = os.path.join(build, 'HTML' , '%s-man.html' % man)
+
+ def strip_to_first_html_tag(target, source, env):
+ t = str(target[0])
+ contents = open(t).read()
+ contents = contents[string.find(contents, '<HTML>'):]
+ open(t, 'w').write(contents)
+ return 0
+
+ cmds = [
+ "( cd %s/man && cp %s .. )" % (build, string.join(man_i_files)),
+ "( cd ${SOURCE.dir} && man2html ${SOURCE.file} ) > $TARGET",
+ Action(strip_to_first_html_tag),
+ ]
+ if tidy:
+ cmds.append("tidy -m -q $TARGET || true")
+ b = env.Command(html, man_1, cmds)
+ Local(html)
+ env.Depends(b, man_intermediate_files)
+
+ tar_deps.append(html)
+ tar_list.append(html)
+
+if not epydoc:
+ print "epydoc not found, skipping building API documentation."
+else:
+ # XXX Should be in common with reading the same thing in
+ # the SConstruct file.
+ e = os.path.join('#src', 'engine')
+ manifest_in = File(os.path.join(e, 'MANIFEST.in')).rstr()
+ sources = map(lambda x: x[:-1], open(manifest_in).readlines())
+ sources = filter(lambda x: string.find(x, 'Optik') == -1, sources)
+ sources = filter(lambda x: string.find(x, 'Platform') == -1, sources)
+ sources = filter(lambda x: string.find(x, 'Tool') == -1, sources)
+ # XXX
+ sources = filter(lambda x: string.find(x, 'Options') == -1, sources)
+
+ e = os.path.join(build, '..', 'scons', 'engine')
+ sources = map(lambda x, e=e: os.path.join(e, x), sources)
+
+ epydoc_commands = [
+ Delete('$OUTDIR'),
+ '$EPYDOC $EPYDOCFLAGS --debug --output $OUTDIR --docformat=restructuredText --name SCons --url http://www.scons.org/ $SOURCES',
+ Touch('$TARGET'),
+ ]
+
+ htmldir = os.path.join(build, 'HTML', 'scons-api')
+ env.Command('${OUTDIR}/index.html', sources, epydoc_commands,
+ EPYDOC=epydoc, EPYDOCFLAGS='--html', OUTDIR=htmldir)
+ tar_deps.append(htmldir)
+ tar_list.append(htmldir)
+
+ # PDF and PostScript and TeX are built from the
+ # same invocation.
+ api_dir = os.path.join(build, 'scons-api')
+ api_pdf = os.path.join(api_dir, 'api.pdf')
+ api_ps = os.path.join(api_dir, 'api.ps')
+ api_tex = os.path.join(api_dir, 'api.tex')
+ api_targets = [api_pdf, api_ps, api_tex]
+ env.Command(api_targets, sources, epydoc_commands,
+ EPYDOC=epydoc, EPYDOCFLAGS='--pdf', OUTDIR=api_dir)
+ Local(api_targets)
+
+ pdf_install = os.path.join(build, 'PDF', 'scons-api.pdf')
+ env.InstallAs(pdf_install, api_pdf)
+ tar_deps.append(pdf_install)
+ tar_list.append(pdf_install)
+ Local(pdf_install)
+
+ ps_install = os.path.join(build, 'PS', 'scons-api.ps')
+ env.InstallAs(ps_install, api_ps)
+ tar_deps.append(ps_install)
+ tar_list.append(ps_install)
+ Local(ps_install)
+
+#
+# Now actually create the tar file of the documentation,
+# for easy distribution to the web site.
+#
+if tar_deps:
+ tar_list = string.join(map(lambda x, b=build+'/': string.replace(x, b, ''),
+ tar_list))
+ t = env.Command(dist_doc_tar_gz, tar_deps,
+ "tar cf${TAR_HFLAG} - -C %s %s | gzip > $TARGET" % (build, tar_list))
+ AddPostAction(dist_doc_tar_gz, Chmod(dist_doc_tar_gz, 0644))
+ Local(t)
+ Alias('doc', t)
+else:
+ Alias('doc', os.path.join(build_dir, 'doc'))