X-Git-Url: http://g0dil.de/git?a=blobdiff_plain;f=senfscons%2FDoxygen.py;h=f422aacd531ecf97aac9b22e14447d118a156a36;hb=f11bb3f5a7eeb232a74d13b7d7ddc6746ca2c2d2;hp=705e22a44cfe0d43471781bea714076f99154c8c;hpb=032707d24b1059febe83ce56b11fd79df106c6e2;p=senf.git diff --git a/senfscons/Doxygen.py b/senfscons/Doxygen.py index 705e22a..f422aac 100644 --- a/senfscons/Doxygen.py +++ b/senfscons/Doxygen.py @@ -15,20 +15,53 @@ # License along with this library; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# I have been fighting 4 problems in this implementation: +# - A Directory target will *not* call any source scanners +# - A Directory target will interpret the directory contents as +# sources not targets. This means, that if a command creates that +# directory plus contents, the target will never be up-to-date +# (since the directory contents will change with every call of +# scons) +# - Theres a bug in SCons which will produce an error message for +# directory targets if dir.sources is not set explicitly +# - the first argument to env.Clean() must be the command line target, +# with which the scons was invoked. This does not help to add +# aditional files or directories to be cleaned if you don't know +# that target (it's not possible to say 'if you clean this file, +# also clean that one' hich is, what I had expected env.Clean to +# do). +# +# Together, these problems have produced several difficulties. I have +# solved them by +# - Adding an (empty) stamp file as a (file) target. This target will +# cause source scanners to be invoked +# - Adding the documentation directory as a target (so it will be +# cleaned up which env.Clean doesn't help me to do), but *only* if +# scons is called to with the -c option +# - Setting dir.sources to the known source-list to silence the error +# message whenever a directory is added as a target +# +# You will find all this in the DoxyEmitter + import os, sys, traceback import os.path -import glob +import glob, re from fnmatch import fnmatch -def DoxyfileParse(file): - data = DoxyfileParse_(file,{}) - for (k,v) in data.items(): +EnvVar = re.compile(r"\$\(([0-9A-Za-z_-]+)\)") + +def DoxyfileParse(env,file): + ENV = {} + ENV.update(env.get("ENV",{})) + ENV['TOPDIR'] = env.Dir('#').abspath + data = DoxyfileParse_(file,{},ENV) + for k,v in data.items(): if not v : del data[k] elif k in ("INPUT", "FILE_PATTERNS", "EXCLUDE_PATTERNS", "@INCLUDE", "TAGFILES") : continue elif len(v)==1 : data[k] = v[0] return data -def DoxyfileParse_(file, data): +def DoxyfileParse_(file, data, ENV): """ Parse a Doxygen source file and return a dictionary of all the values. Values will be strings and lists of strings. @@ -38,7 +71,7 @@ def DoxyfileParse_(file, data): import shlex lex = shlex.shlex(instream=open(file), posix=True) - lex.wordchars += "*+./-:@~" + lex.wordchars += "*+./-:@~$()" lex.whitespace = lex.whitespace.replace("\n", "") lex.escape = "\\" @@ -72,12 +105,13 @@ def DoxyfileParse_(file, data): elif token == "=": data[key] = [] else: + token = EnvVar.sub(lambda m,ENV=ENV: str(ENV.get(m.group(1),"")),token) 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_(inc,data) + DoxyfileParse_(inc,data,ENV) last_token = token token = lex.get_token() @@ -112,7 +146,7 @@ def DoxySourceScan(node, env, path): sources = [] basedir = node.dir.abspath - data = DoxyfileParse(node.abspath) + data = DoxyfileParse(env, node.abspath) recursive = data.get("RECURSIVE", "NO").upper()=="YES" file_patterns = data.get("FILE_PATTERNS", default_file_patterns) exclude_patterns = data.get("EXCLUDE_PATTERNS", default_exclude_patterns) @@ -158,30 +192,25 @@ def DoxyEmitter(source, target, env): "XML" : ("NO", "xml"), } - data = DoxyfileParse(source[0].abspath) + data = DoxyfileParse(env, source[0].abspath) targets = [] if data.has_key("OUTPUT_DIRECTORY"): out_dir = data["OUTPUT_DIRECTORY"] dir = env.Dir( os.path.join(source[0].dir.abspath, out_dir) ) dir.sources = source - targets.append(dir) + if env.GetOption('clean'): targets.append(dir) else: out_dir = '.' # add our output locations for (k, v) in output_formats.iteritems(): if data.get("GENERATE_" + k, v[0]).upper() == "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 !! dir = env.Dir( os.path.join(source[0].dir.abspath, out_dir, data.get(k + "_OUTPUT", v[1])) ) - # This is needed to silence the (wrong) 'Multiple ways to - # build the same target' message dir.sources = source - node = env.File( os.path.join(dir.abspath, ".stamp" ) ) + node = env.File( os.path.join(dir.abspath, k.lower()+".stamp" ) ) targets.append(node) - targets.append(dir) + if env.GetOption('clean'): targets.append(dir) if data.has_key("GENERATE_TAGFILE"): targets.append(env.File( os.path.join(source[0].dir.abspath, data["GENERATE_TAGFILE"]) )) @@ -192,9 +221,9 @@ def DoxyEmitter(source, target, env): return (targets, source) -def doxyNodeHtmlDir(node): +def doxyNodeHtmlDir(env,node): if not node.sources : return None - data = DoxyfileParse(node.sources[0].abspath) + data = DoxyfileParse(env, node.sources[0].abspath) if data.get("GENERATE_HTML",'YES').upper() != 'YES' : return None return os.path.normpath(os.path.join( node.sources[0].dir.abspath, data.get("OUTPUT_DIRECTORY","."), @@ -214,9 +243,10 @@ def relpath(source, target): def DoxyGenerator(source, target, env, for_signature): - data = DoxyfileParse(source[0].abspath) + data = DoxyfileParse(env, source[0].abspath) - actions = [ env.Action("cd ${SOURCE.dir} && ${DOXYGEN} ${SOURCE.file}") ] + actions = [ env.Action("cd ${SOURCE.dir} && TOPDIR=%s ${DOXYGEN} ${SOURCE.file}" + % (relpath(source[0].dir.abspath, env.Dir('#').abspath),)) ] # This will add automatic 'installdox' calls. # @@ -246,6 +276,7 @@ def DoxyGenerator(source, target, env, for_signature): url = env.get(os.path.splitext(os.path.basename(tagfile))[0].upper()+"_DOXY_URL", None) if not url: url = doxyNodeHtmlDir( + env, env.File(os.path.normpath(os.path.join(str(source[0].dir), tagfile)))) if url : url = relpath(output_dir, url) if not url: