From: g0dil Date: Wed, 13 Dec 2006 13:07:06 +0000 (+0000) Subject: Use new Doxygen tool from the SCons wiki X-Git-Url: http://g0dil.de/git?a=commitdiff_plain;h=11b5ed5acaf415f8a3d1ebb165aab76ea7c71179;p=senf.git Use new Doxygen tool from the SCons wiki git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@161 270642c3-0616-0410-b53a-bc976706d245 --- diff --git a/Packets/SConscript b/Packets/SConscript index 38ee2ba..d4a304a 100644 --- a/Packets/SConscript +++ b/Packets/SConscript @@ -8,6 +8,6 @@ import SatSCons sources = SatSCons.GlobSources() SatSCons.StandardTargets(env) SatSCons.Lib(env, 'Packets', sources, ) -SatSCons.Doxygen(env,sources,SatSCons.DoxyGlob(), - image = [ "structure.dia" ]) - +SatSCons.Doxygen(env, extra_sources = [ + env.Dia2Png("structure.dia") + ]) diff --git a/SConstruct b/SConstruct index 04ad6ba..5271e8d 100644 --- a/SConstruct +++ b/SConstruct @@ -1,17 +1,22 @@ +# -*- python -*- + import sys, glob sys.path.append('satscons') import SatSCons ########################################################################### -SatSCons.UseBoost(); -SatSCons.UseSTLPort(); -SatSCons.UseDoxygen(); -env = SatSCons.MakeEnvironment(); +SatSCons.UseBoost() +SatSCons.UseSTLPort() +SatSCons.UseDoxygen() +env = SatSCons.MakeEnvironment() +env.Tool('Dia2Png', [ 'satscons' ]) env.Append( CPPPATH = [ '#' ], - LIBS = [ 'iberty' ] + LIBS = [ 'iberty' ], + DOXYFILES = [ '#/doclib/doxy-header.html', '#/doclib/doxy-footer.html', + '#/doclib/Doxyfile.global' ] ) Export('env') @@ -20,4 +25,4 @@ SConscript(glob.glob("*/SConscript")) SatSCons.StandardTargets(env) SatSCons.GlobalTargets(env) -SatSCons.Doxygen(env, SatSCons.DoxyGlob()) \ No newline at end of file +SatSCons.Doxygen(env) diff --git a/Scheduler/SConscript b/Scheduler/SConscript index 3ea2bc1..cbdb925 100644 --- a/Scheduler/SConscript +++ b/Scheduler/SConscript @@ -11,4 +11,4 @@ SatSCons.Lib(env, library = 'Scheduler', sources = sources, LIBS = [ 'Socket', 'Utils' ]) -SatSCons.Doxygen(env, sources, SatSCons.DoxyGlob()) +SatSCons.Doxygen(env) diff --git a/Socket/SConscript b/Socket/SConscript index 72af964..27cb277 100644 --- a/Socket/SConscript +++ b/Socket/SConscript @@ -14,5 +14,6 @@ SatSCons.Lib(env, sources = sources, LIBS = [ 'Utils' ]) -SatSCons.Doxygen(env,sources,SatSCons.DoxyGlob(), - image=[ 'SocketLibrary-classes.dia' ]) +SatSCons.Doxygen(env, extra_sources = [ + env.Dia2Png('SocketLibrary-classes.dia') + ]) diff --git a/Utils/SConscript b/Utils/SConscript index 373bffc..c679e5f 100644 --- a/Utils/SConscript +++ b/Utils/SConscript @@ -8,4 +8,4 @@ import SatSCons sources = SatSCons.GlobSources() SatSCons.StandardTargets(env) SatSCons.Lib(env, 'Utils', sources) -SatSCons.Doxygen(env, sources, SatSCons.DoxyGlob()) +SatSCons.Doxygen(env) diff --git a/satscons/Dia2Png.py b/satscons/Dia2Png.py index 5f8af49..d536ebf 100644 --- a/satscons/Dia2Png.py +++ b/satscons/Dia2Png.py @@ -9,9 +9,10 @@ import SCons.Builder def dia_getSize(env,source): size = None - for line in popen(env['DIACOM']+" -e /proc/self/fd/1 -t eps "+source[0],"r"): + for line in os.popen(env['DIACOM']+" -e /proc/self/fd/1 -t eps "+str(source[0]),"r"): if line.startswith("%%BoundingBox:"): - size=map(int,line.split()[4:]) + size=map(int,line.split()[3:]) + break return size def dia2png_generator(source, target, env, for_signature): @@ -19,9 +20,9 @@ def dia2png_generator(source, target, env, for_signature): return "$DIACOM -t png -s $DIA2PNGDPI $TARGET $SOURCE" size = dia_getSize(env,source) if not size: return None; - size[0] = size[0]*72/int(env['DIA2PNGDPI']) - size[1] = size[1]*72/int(env['$DIA2PNGDPI']) - return env.Action("$DIACOM -t png -s %dx%d $TARGET $SOURCE" % size) + size[0] = size[0]*int(env['DIA2PNGDPI'])/72 + size[1] = size[1]*int(env['DIA2PNGDPI'])/72 + return env.Action("$DIACOM -t png -s %dx%d -e $TARGET $SOURCE" % tuple(size)) Dia2Png = SCons.Builder.Builder(suffix = ".png", src_suffix = ".dia", @@ -34,4 +35,4 @@ def generate(env): env['DIA2PNGDPI'] = 115 def exists(env): - return 1 + return env.Detect("dia") diff --git a/satscons/Doxygen.py b/satscons/Doxygen.py index 9c78586..c934dc0 100644 --- a/satscons/Doxygen.py +++ b/satscons/Doxygen.py @@ -1,32 +1,233 @@ -import SCons.Script.SConscript -import SCons.Builder -import SCons.Defaults +# Astxx, the Asterisk C++ API and Utility Library. +# Copyright (C) 2005, 2006 Matthew A. Nicholson +# Copyright (C) 2006 Tim Blechmann +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License version 2.1 as published by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +import os, sys, traceback import os.path +import glob +from fnmatch import fnmatch + +def DoxyfileParse(file_contents, dir, data = None): + """ + Parse a Doxygen source file and return a dictionary of all the values. + Values will be strings and lists of strings. + """ + try: + if data is None : data = {} + + import shlex + lex = shlex.shlex(instream = file_contents, posix = True) + lex.wordchars += "*+./-:" + lex.whitespace = lex.whitespace.replace("\n", "") + lex.escape = "" + + lineno = lex.lineno + token = lex.get_token() + key = None + last_token = "" + key_token = True + next_key = False + new_data = True + + def append_data(data, key, new_data, token): + if new_data or len(data[key]) == 0: + data[key].append(token) + else: + data[key][-1] += token + + while token: + if token in ['\n']: + if last_token not in ['\\']: + key_token = True + elif token in ['\\']: + pass + elif key_token: + if key == '@' : key += token + else : key = token + if token != '@' : key_token = False + else: + if token == "+=" or (token == "==" and key == "@INCLUDE"): + if not data.has_key(key): + data[key] = list() + elif token == "=": + data[key] = list() + else: + append_data( data, key, new_data, token ) + new_data = True + if key == '@INCLUDE': + inc = os.path.join(dir,data['@INCLUDE'][-1]) + if os.path.exists(inc) : + DoxyfileParse(open(inc).read(),dir,data) + + last_token = token + token = lex.get_token() + + if last_token == '\\' and token != '\n': + new_data = False + append_data( data, key, new_data, '\\' ) + + # compress lists of len 1 into single strings + for (k, v) in data.items(): + if k == "@INCLUDE" : continue + if len(v) == 0: + data.pop(k) + + # items in the following list will be kept as lists and not converted to strings + if k in ["INPUT", "FILE_PATTERNS", "EXCLUDE_PATTERNS"]: + continue + + if len(v) == 1: + data[k] = v[0] + + return data + except: + return {} + +def DoxySourceScan(node, env, path): + """ + Doxygen Doxyfile source scanner. This should scan the Doxygen file and add + any files used to generate docs to the list of source files. + """ + default_file_patterns = [ + '*.c', '*.cc', '*.cxx', '*.cpp', '*.c++', '*.java', '*.ii', '*.ixx', + '*.ipp', '*.i++', '*.inl', '*.h', '*.hh ', '*.hxx', '*.hpp', '*.h++', + '*.idl', '*.odl', '*.cs', '*.php', '*.php3', '*.inc', '*.m', '*.mm', + '*.py', + ] + + default_exclude_patterns = [ + '*~', + ] + + sources = [] + + data = DoxyfileParse(node.get_contents(), str(node.dir)) + + if data.get("RECURSIVE", "NO") == "YES": + recursive = True + else: + recursive = False + + file_patterns = data.get("FILE_PATTERNS", default_file_patterns) + exclude_patterns = data.get("EXCLUDE_PATTERNS", default_exclude_patterns) -def replace_ext(n,ext): - base,ext = os.path.splitext(n) - return base+ext - -def Doxygen(env, target, source, image=[]): - global __file__ - path, name = os.path.split(str(target)) - stamp = os.path.join(path, '.'+name+'.stamp') - dir = env.Dir(target) - mak = os.path.join(os.path.split(__file__)[0],'imgconvert.mak') - env.Depends(dir, - [ env.Command(os.path.splitext(img)[0]+".png", img, - [ 'TERM=dumb make -f %s $TARGET' % mak ]) - for img in image ] + - [ env.Command(stamp, source + [ os.path.join(path,"Doxyfile") ], - [ 'cd $TARGET.dir && $DOXYGENCOM', - "touch $TARGET" ], - source_scanner = SCons.Defaults.ObjSourceScan) ]) - env.Clean(stamp, dir) - return dir + for i in data.get("INPUT", [ "." ]): + input = os.path.normpath(os.path.join(str(node.dir),i)) + if os.path.isfile(input): + sources.append(input) + elif os.path.isdir(input): + if recursive: + entries = os.walk(input) + else: + entries = [ (input, [], os.listdir(input)) ] + for root, dirs, files in entries: + for f in files: + filename = os.path.join(root, f) + + pattern_check = reduce(lambda x, y: x or bool(fnmatch(filename, y)), file_patterns, False) + exclude_check = reduce(lambda x, y: x and fnmatch(filename, y), exclude_patterns, True) + + if pattern_check and not exclude_check: + sources.append(filename) + + sources.extend([ os.path.normpath(os.path.join(str(node.dir),x)) + for x in data.get("@INCLUDE",[]) ]) + + for key in ('HTML_HEADER','HTML_FOOTER','TAGFILES'): + if data.has_key(key): + elt = data[key] + if type(elt) is type ("") : elt = [ elt ] + sources.extend([ os.path.normpath(os.path.join(str(node.dir),f)) + for f in elt ]) + + sources = map( lambda path: env.File(path), sources ) + return sources + +def DoxySourceScanCheck(node, env): + """Check if we should scan this file""" + return os.path.isfile(node.path) + +def DoxyEmitter(source, target, env): + """Doxygen Doxyfile emitter""" + # possible output formats and their default values and output locations + output_formats = { + "HTML": ("YES", "html"), + "LATEX": ("YES", "latex"), + "RTF": ("NO", "rtf"), + "MAN": ("YES", "man"), + "XML": ("NO", "xml"), + } + + data = DoxyfileParse(source[0].get_contents(), str(source[0].dir)) + + targets = [] + out_dir = data.get("OUTPUT_DIRECTORY", ".") + + # add our output locations + for (k, v) in output_formats.items(): + if data.get("GENERATE_" + k, v[0]) == "YES": + # Grmpf ... need to use a File object here. The problem is, that + # Dir.scan() is implemented to just return the directory entries + # and does *not* invoke the source-file scanners .. ARGH !! + node = env.File( os.path.join(str(source[0].dir), out_dir, data.get(k + "_OUTPUT", v[1]), ".stamp" )) + targets.append( node ) + + if data.has_key("GENERATE_TAGFILE"): + targets.append(env.File( os.path.join(str(source[0].dir), data["GENERATE_TAGFILE"]) )) + + # don't clobber targets + for node in targets: + env.Precious(node) + + # set up cleaning stuff + for node in targets: + env.Clean(node, node) + + return (targets, source) def generate(env): - env['DOXYGENCOM'] = 'doxygen' - env.__class__.Doxygen = Doxygen + """ + Add builders and construction variables for the + Doxygen tool. This is currently for Doxygen 1.4.6. + """ + doxyfile_scanner = env.Scanner( + DoxySourceScan, + "DoxySourceScan", + scan_check = DoxySourceScanCheck, + ) + + doxyfile_builder = env.Builder( + # scons 0.96.93 hang on the next line but I don't know hot to FIX the problem + action = env.Action("( cd ${SOURCE.dir} && ${DOXYGEN} ${SOURCE.file} ) && touch $TARGETS"), + emitter = DoxyEmitter, + target_factory = env.fs.Entry, + single_source = True, + source_scanner = doxyfile_scanner + ) + + env.Append(BUILDERS = { + 'Doxygen': doxyfile_builder, + }) + + env.AppendUnique( + DOXYGEN = 'doxygen', + ) def exists(env): - return 1 + """ + Make sure doxygen exists. + """ + return env.Detect("doxygen") diff --git a/satscons/SatSCons.py b/satscons/SatSCons.py index 169b0f3..8b10deb 100644 --- a/satscons/SatSCons.py +++ b/satscons/SatSCons.py @@ -154,19 +154,11 @@ def DoxyGlob(exclude=[]): if f not in exclude ] return sources -def Doxygen(env, cc_sources = [], doc_sources = None, target='doc', image = []): - if type(cc_sources) == type(()): - cc_sources = cc_sources[0] - sources = cc_sources - if doc_sources is not None: - sources += doc_sources - doc = env.Doxygen( - target = target, - source = sources, - image = image) - - env.Alias('all_docs', doc) - return doc +def Doxygen(env, doxyfile="Doxyfile", extra_sources = []): + docs = env.Doxygen(doxyfile) + env.Depends(docs,extra_sources) + env.Alias('all_docs', *docs) + return docs def Lib(env, library, sources, testSources = None, LIBS = []): objects = Objects(env,sources,testSources,LIBS=LIBS) diff --git a/satscons/imgconvert.mak b/satscons/imgconvert.mak deleted file mode 100644 index baf1b0d..0000000 --- a/satscons/imgconvert.mak +++ /dev/null @@ -1,179 +0,0 @@ - -PSTOPNG_DPI := 100 - -CLEAN_FILE := $(shell pwd)/.clean -clean := clean() { \ - touch $(CLEAN_FILE); \ - for file in "$$@"; do \ - grep "^$$file"'$$' $(CLEAN_FILE) >/dev/null || echo $$file >>$(CLEAN_FILE); \ - done \ -}; clean - -cmd := run() { tput bold; echo -e "--[ $$* ]"; tput sgr0; } && run -do := run() { tput bold; echo -e "--[ $$* ]"; tput sgr0; "$$@"; } && run -eval := run() { tput bold; echo -e "--[ $$* ]"; tput sgr0; eval "$$@"; } && run - -Q := @ - -%.rawtex: %.stxt - $(Q)$(clean) $@ - $(Q)$(cmd) "rest2latex $< >$@"; \ - rest2latex \ - --language=de \ - --documentclass=scrreprt \ - --documentoptions="10pt,a4paper,DIV10" \ - --table-style=booktabs \ - --use-verbatim-when-possible \ - --use-latex-footnotes \ - --use-latex-toc \ - --no-section-numbering \ - --stylesheet=default.sty \ - --exit-status=2 \ - $< \ - > $@ || (rm -f $@; exit 1) - -%.tex: %.rawtex - $(Q)$(clean) $@ - $(Q)$(cmd) "rawfilter $< >$@"; \ - sed -e 's/\.\(png\|gif\|jpg\)/.pdf/g' \ - -e 's/\[htbp\]/\[tbp\]/g' $< >$@ \ - || (rm -f $@; exit 1) - -%.html: %.stxt - $(Q)$(clean) $@ - $(Q)$(cmd) "rest2html $< >$@"; \ - up="`echo $< | sed -r -e 's,^[^/]*$$,,' -e 's,/[^/]+$$,/,' -e 's,[^/]+,..,g'`"; \ - rest2html \ - --language=de \ - --exit-status=2 \ - --stylesheet-path="$${up}default.css" \ - $< \ - > $@ || (rm -f $@; exit 1) - -%.pdf: %.tex - $(Q)( \ - dir="$$(dirname $<)"; \ - up="echo $$dir | sed -e 's,[^/]\+,..,g"; \ - [ -n "$$dir" ] && dir="$$dir/"; \ - stem="$$(basename $*)"; \ - tex="$$(basename $<)"; \ - pdf="$$(basename $@)"; \ - $(clean) $${dir}texput.log; \ - cd "$$dir"; \ - repeat=5; \ - origfiles="$$(find $$stem.* ! \( -name $$pdf -o -name $$stem.log \) \ - -maxdepth 0 -printf '%p-%TY%Tm%Td%TH%TM%TS\n')"; \ - while [ $$repeat -gt 0 ]; do \ - $(cmd) "pdflatex --interaction nonstopmode $$tex"; \ - TEXINPUTS=.:$$up: pdflatex --interaction nonstopmode $$tex; \ - pdfexit=$$?; \ - auxfiles=$$((echo $$origfiles | tr ' ' '\n'; \ - find $$stem.* ! \( -name $$pdf -o -name $$stem.log \) \ - -maxdepth 0 -printf '%p-%TY%Tm%Td%TH%TM%TS\n') \ - | sort | uniq -u | sed -e 's/-[0-9]*$$//' | sort -u ); \ - for f in $$auxfiles; do \ - $(clean) $$dir$$f; \ - done; \ - $(clean) $*.log $@; \ - [ $$pdfexit -ne 0 ] && exit $$pdfexit; \ - newauxsum=`md5sum $$auxfiles | md5sum 2>/dev/null`; \ - [ "$$auxsum" = "$$newauxsum" ] && break; \ - auxsum="$$newauxsum"; \ - repeat=$$[ $$repeat - 1 ]; \ - done; \ - ) || (rm -f $@; exit 1) - -%.png: %.sxd - $(Q)$(clean) $@ - $(Q)$(cmd) "(openoffice) sxdtopng $<"; \ - openoffice -invisible "macro:///Local.Conversion.ConvertDrawToPNG($(shell realpath $<))" - -%.pdf: %.sxd - $(Q)$(clean) $@ - $(Q)$(cmd) "(openoffice) sxdtopdf $<"; \ - openoffice -invisible "macro:///Local.Conversion.ConvertDrawToPDF($(shell realpath $<))" - -%.pdf: %.sxc - $(Q)$(clean) $@ - $(Q)$(cmd) "(openoffice) sxctopdf $<"; \ - openoffice -invisible "macro:///Local.Conversion.ConvertCalcToPDF($(shell realpath $<))" - -%.ps: %.pdf - $(Q)$(clean) $@ - $(Q)$(cmd) "pdftops $< >$@"; \ - pdftops -eps -nocrop -noshrink -nocenter $< - | pstops - >$@ || (rm -f $@; exit 1) - -%.png: %.ps - $(Q)$(clean) $@ - $(Q)$(cmd) "pstopng $< >$@"; \ - bb=$$(grep -i '^%%BoundingBox:' $< | head -1 | sed -e 's/^%%BoundingBox: *//i'); \ - bbx=$${bb% *}; \ - bbx=$${bbx##* }; \ - bby=$${bb##* }; \ - pngx=$$(dc -e "$$bbx $(PSTOPNG_DPI) * 8 * 75.45 / p"); \ - pngy=$$(dc -e "$$bby $(PSTOPNG_DPI) * 8 * 75.45 / p"); \ - pstopnm -xborder 0 -yborder 0 -portrait -nocrop -stdout -xsize $$pngx -ysize $$pngy $< \ - | pnmscale -reduce 8 \ - | pnmtopng >$@ \ - || (rm -f $@; exit 1) - -%.gif: %.png - $(Q)$(clean) $@ - $(Q)$(cmd) "pngtogif $< >$@" - $(Q)pngtopnm $< | ppmquant 256 | ppmtogif >$@ || ( rm -f $@; exit 1) - -%.pdf: %.dot - $(Q)$(clean) $@ - $(Q)$(eval) "dot -Tfig $< | fig2dev -L pdf -f Helvetica >$@" || ( rm -f $@; exit 1 ) - -%.pdf: %.neato - $(Q)$(clean) $@ - $(Q)$(eval) "neato -Tfig $< | fig2dev -L pdf -f Helvetica >$@" || ( rm -f $@; exit 1 ) - -%.eps: %.dia - $(Q)$(clean) $@ - $(Q)$(do) dia -t eps -e $@ $< - -%.pdf: %.eps - $(Q)$(clean) $@ - $(Q)$(do) epstopdf --outfile=$@ $< - -%.d: %.stxt - $(Q)$(clean) $@ - $(Q) \ - $(cmd) "makedep $<"; \ - base="$$(dirname $<)"; \ - [ -n "$$base" ] && base="$${base}/"; \ - function scaninc { \ - local includes; \ - [ -r $$1 ] || return; \ - includes="$$(sed -n -e 's/^.. \+include:: *//' -e T -e p $$1)"; \ - for include in $$includes; do \ - echo $$base$$include; \ - scaninc $$base$$include; \ - done \ - }; \ - includes="$$(scaninc $<)"; \ - figures="$$(sed -n -e "s,^.. \+figure:: *,$$base," -e T -e p $< $$includes)"; \ - \ - echo "$*_Includes := $$(echo $$includes)" >$@; \ - echo "$*_Figures := $$(echo $$figures)" >>$@; \ - echo "$*_PDFs := $$(echo $$figures | sed -e 's/\.\(gif\|png\|jpg\)/.pdf/g')" >>$@; \ - echo '$@: Makefile $< $$($*_Includes)' >>$@; \ - echo '$*.html: $< $$($*_Includes)' >>$@; \ - echo '$*_html: $*.html $$($*_Figures)' >>$@; \ - echo '$*.tex: $< $$($*_Includes)' >>$@; \ - echo '$*.pdf: $*.tex $$($*_PDFs) $(TEX_STYLE)' >>$@ - -########################################################################### - -clean: - $(Q)if [ -r $(CLEAN_FILE) ]; then \ - $(cmd) "xargs rm -f <.clean && rm -f .clean"; \ - xargs rm -f <$(CLEAN_FILE) && rm -f $(CLEAN_FILE); \ - fi - -# Local Variables: -# mode: makefile -# makefile-backslash-column: 100 -# End: