## SConscript file for building SCons documentation.### __COPYRIGHT__## 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.#importos.pathimportreimportstringImport('build_dir','env','whereis')env=env.Clone()env.TargetSignatures('content')build=os.path.join(build_dir,'doc')###doc_tar_gz=os.path.join(build_dir,'dist','scons-doc-%s.tar.gz'%env.Dictionary('VERSION'))## 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=whereis('jade')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 .sgml files:## <!entity bground SYSTEM "bground.sgml"># <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.#defscansgml(node,env,target):includes=[]contents=node.get_contents()includes.extend(entity_re.findall(contents))matches=format_re.findall(contents)forminmatches:file,format=mifformatandfile[-len(format):]!=format:file=file+'.'+formatifnotos.path.isabs(file):a=[]f=filewhilef:f,tail=os.path.split(f)iftail=='doc':breaka=[tail]+afile=apply(os.path.join,a,{})includes.append(file)returnincludess=Scanner(name='sgml',function=scansgml,skeys=['.sgml','.mod'])orig_env=envenv=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.defchop(s):returns[:-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(lambdax:File('#src/engine/'+x).rstr(),scons_doc_files)ifjw:## Always create a version.sgml 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_sgml=File(os.path.join(build,"version.sgml"))#version_sgml = File("version.sgml")verfile=str(version_sgml)try:os.unlink(verfile)exceptOSError:pass# okay if the file didn't existdir,f=os.path.split(verfile)try:os.makedirs(dir)exceptOSError:pass# okay if the directory already existsopen(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 --sgml -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 SGML files which# get included by the document SGML files in the subdirectories.#manifest=File('MANIFEST').rstr()src_files=map(lambdax:x[:-1],open(manifest).readlines())forsinsrc_files:base,ext=os.path.splitext(s)ifextin['.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.#fordocindocs.keys():manifest=File(os.path.join(doc,'MANIFEST')).rstr()src_files=map(lambdax:x[:-1],open(manifest).readlines())build_doc=docs[doc].get('sconsoutput')andint(ARGUMENTS.get('BUILDDOC',0))forsinsrc_files:doc_s=os.path.join(doc,s)build_s=os.path.join(build,doc,s)base,ext=os.path.splitext(doc_s)ifextin['.fig','.jpg']:orig_env.InstallAs(build_s,doc_s)else:ifbuild_docandext=='.sgml':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.sgml')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_sgml)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)ifdocs[doc].get('html')andjade:cmds=[Delete("${TARGET.dir}/*.html"),"jw -b html -o ${TARGET.dir} $SOURCES",]iftidy:cmds.append("tidy -m -q $TARGET || true")env.Command(htmlindex,main,cmds)Local(htmlindex)cmds=[Delete("${TARGET.dir}/main.html"),"jw -u -b html -o ${TARGET.dir} $SOURCES",Move("$TARGET","${TARGET.dir}/main.html"),]iftidy:cmds.append("tidy -m -q $TARGET || true")env.Command(html,main,cmds)Local(html)env.Ignore([html,htmlindex],version_sgml)tar_deps.extend([html,htmlindex])tar_list.extend([html,htmldir])forgindocs[doc].get('graphics',[]):base,ext=os.path.splitext(g)ifext=='.fig':jpg=base+'.jpg'htmldir_jpg=os.path.join(htmldir,jpg)iffig2dev: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))ifdocs[doc].get('ps')andjadetex:env.Command(ps,main,[Delete("${TARGET.dir}/%s"%out),"jw -b ps -o ${TARGET.dir} $SOURCES","mv ${TARGET.dir}/main.ps $TARGET",Delete("${TARGET.dir}/%s"%out),])Local(ps)env.Ignore(ps,version_sgml)tar_deps.append(ps)tar_list.append(ps)forgindocs[doc].get('graphics',[]):base,ext=os.path.splitext(g)ifext=='.fig':eps=base+'.eps'build_eps=os.path.join(build,'PS',eps)iffig2dev: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))ifdocs[doc].get('pdf')andpdfjadetex:env.Command(pdf,main,[Delete("${TARGET.dir}/%s"%out),"jw -b pdf -o ${TARGET.dir} $SOURCES","mv ${TARGET.dir}/main.pdf $TARGET",Delete("${TARGET.dir}/out"),])Local(pdf)env.Ignore(pdf,version_sgml)tar_deps.append(pdf)tar_list.append(pdf)ifdocs[doc].get('text')andjadeandlynx:env.Command(text,html,"lynx -dump ${SOURCE.abspath} > $TARGET")Local(text)env.Ignore(text,version_sgml)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']forminman_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(lambdax: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)forman_1inman_page_list:man,_1=os.path.splitext(man_1)man_1=os.path.join(build,'man',man_1)ifgroff: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])ifman2html:html=os.path.join(build,'HTML','%s-man.html'%man)defstrip_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)return0cmds=["( cd %s/man && cp %s .. )"%(build,string.join(man_i_files)),"( cd ${SOURCE.dir} && man2html ${SOURCE.file} ) > $TARGET",Action(strip_to_first_html_tag),]iftidy: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)ifepydoc:# 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(lambdax:x[:-1],open(manifest_in).readlines())sources=filter(lambdax:string.find(x,'Optik')==-1,sources)sources=filter(lambdax:string.find(x,'Platform')==-1,sources)sources=filter(lambdax:string.find(x,'Tool')==-1,sources)# XXXsources=filter(lambdax:string.find(x,'Options')==-1,sources)e=os.path.join(build,'..','scons','engine')sources=map(lambdax,e=e:os.path.join(e,x),sources)epydoc_commands=[Delete('$OUTDIR'),'$EPYDOC $EPYDOCFLAGS --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.#iftar_deps:tar_list=string.join(map(lambdax,b=build+'/':string.replace(x,b,''),tar_list))env.Command(doc_tar_gz,tar_deps,"tar cf${TAR_HFLAG} - -C %s%s | gzip > $TARGET"%(build,tar_list))Local(doc_tar_gz)