32 from fnmatch
import fnmatch
35 def DoxyfileParse(file_contents):
36 """ Parse a Doxygen source file and return a dictionary of all the values. 37 Values will be strings and lists of strings. 42 lex = shlex.shlex(instream = file_contents, posix =
True)
43 lex.wordchars +=
"*+./-:" 44 lex.whitespace = lex.whitespace.replace(
"\n",
"")
48 token = lex.get_token()
55 def append_data(data, key, new_data, token):
56 if new_data
or len(data[key]) == 0:
57 data[key].append(token)
59 data[key][-1] += token
63 if last_token
not in [
'\\']:
72 if not data.has_key(key):
77 append_data(data, key, new_data, token)
81 token = lex.get_token()
83 if last_token ==
'\\' and token !=
'\n':
85 append_data(data, key, new_data,
'\\')
88 for (k, v)
in data.items():
93 if k
in [
"INPUT",
"FILE_PATTERNS",
"EXCLUDE_PATTERNS"]:
102 def DoxySourceScan(node, env, path):
103 """ Doxygen Doxyfile source scanner. 104 This should scan the Doxygen file and add any files 105 used to generate docs to the list of source files. 107 default_file_patterns = [
108 '*.c',
'*.cc',
'*.cxx',
'*.cpp',
'*.c++',
'*.java',
'*.ii',
'*.ixx',
109 '*.ipp',
'*.i++',
'*.inl',
'*.h',
'*.hh ',
'*.hxx',
'*.hpp',
'*.h++',
110 '*.idl',
'*.odl',
'*.cs',
'*.php',
'*.php3',
'*.inc',
'*.m',
'*.mm',
114 default_exclude_patterns = [
120 data = DoxyfileParse(node.get_contents())
122 if data.get(
"RECURSIVE",
"NO") ==
"YES":
127 file_patterns = data.get(
"FILE_PATTERNS", default_file_patterns)
128 exclude_patterns = data.get(
"EXCLUDE_PATTERNS", default_exclude_patterns)
134 conf_dir = os.path.dirname(str(node))
136 for node
in data.get(
"INPUT", []):
137 if not os.path.isabs(node):
138 node = os.path.join(conf_dir, node)
139 if os.path.isfile(node):
141 elif os.path.isdir(node):
143 for root, dirs, files
in os.walk(node):
145 filename = os.path.join(root, f)
147 pattern_check =
reduce(
lambda x, y: x
or bool(fnmatch(filename, y)), file_patterns,
False)
148 exclude_check =
reduce(
lambda x, y: x
and fnmatch(filename, y), exclude_patterns,
True)
150 if pattern_check
and not exclude_check:
151 sources.append(filename)
153 for pattern
in file_patterns:
154 sources.extend(glob.glob(
"/".join([node, pattern])))
156 sources = map(
lambda path: env.File(path), sources )
160 def DoxySourceScanCheck(node, env):
161 """ Check if we should scan this file """ 162 return os.path.isfile(node.path)
165 def DoxyEmitter(source, target, env):
166 """ Doxygen Doxyfile emitter """ 169 "HTML": (
"YES",
"html"),
170 "LATEX": (
"YES",
"latex"),
171 "RTF": (
"NO",
"rtf"),
172 "MAN": (
"NO",
"man"),
173 "XML": (
"NO",
"xml"),
176 data = DoxyfileParse(source[0].get_contents())
179 out_dir = data.get(
"OUTPUT_DIRECTORY",
".")
182 for (k, v)
in output_formats.items():
183 if data.get(
"GENERATE_" + k, v[0]) ==
"YES":
184 targets.append(env.Dir( os.path.join(out_dir, data.get(k +
"_OUTPUT", v[1]))) )
192 env.Clean(node, node)
194 return (targets, source)
198 """ Add builders and construction variables for the 199 Doxygen tool. This is currently for Doxygen 1.4.6. 201 doxyfile_scanner = env.Scanner(
204 scan_check = DoxySourceScanCheck,
208 doxyfile_builder = SCons.Builder.Builder(
209 action =
"cd ${SOURCE.dir} && (${DOXYGEN} ${SOURCE.file} 2>&1 |tee ,doxylog)",
210 emitter = DoxyEmitter,
211 target_factory = env.fs.Entry,
212 single_source =
True,
213 source_scanner = doxyfile_scanner,
216 env.Append(BUILDERS = {
217 'Doxygen': doxyfile_builder,
226 """ Make sure doxygen exists. 228 return env.Detect(
"doxygen")