25 from fnmatch
import fnmatch
28 def DoxyfileParse(file_contents):
29 """ Parse a Doxygen source file and return a dictionary of all the values. 30 Values will be strings and lists of strings. 35 lex = shlex.shlex(instream = file_contents, posix =
True)
36 lex.wordchars +=
"*+./-:" 37 lex.whitespace = lex.whitespace.replace(
"\n",
"")
41 token = lex.get_token()
48 def append_data(data, key, new_data, token):
49 if new_data
or len(data[key]) == 0:
50 data[key].append(token)
52 data[key][-1] += token
56 if last_token
not in [
'\\']:
65 if not data.has_key(key):
70 append_data(data, key, new_data, token)
74 token = lex.get_token()
76 if last_token ==
'\\' and token !=
'\n':
78 append_data(data, key, new_data,
'\\')
81 for (k, v)
in data.items():
86 if k
in [
"INPUT",
"FILE_PATTERNS",
"EXCLUDE_PATTERNS"]:
95 def DoxySourceScan(node, env, path):
96 """ Doxygen Doxyfile source scanner. 97 This should scan the Doxygen file and add any files 98 used to generate docs to the list of source files. 100 default_file_patterns = [
101 '*.c',
'*.cc',
'*.cxx',
'*.cpp',
'*.c++',
'*.java',
'*.ii',
'*.ixx',
102 '*.ipp',
'*.i++',
'*.inl',
'*.h',
'*.hh ',
'*.hxx',
'*.hpp',
'*.h++',
103 '*.idl',
'*.odl',
'*.cs',
'*.php',
'*.php3',
'*.inc',
'*.m',
'*.mm',
107 default_exclude_patterns = [
113 data = DoxyfileParse(node.get_contents())
115 if data.get(
"RECURSIVE",
"NO") ==
"YES":
120 file_patterns = data.get(
"FILE_PATTERNS", default_file_patterns)
121 exclude_patterns = data.get(
"EXCLUDE_PATTERNS", default_exclude_patterns)
127 conf_dir = os.path.dirname(str(node))
129 for node
in data.get(
"INPUT", []):
130 if not os.path.isabs(node):
131 node = os.path.join(conf_dir, node)
132 if os.path.isfile(node):
134 elif os.path.isdir(node):
136 for root, dirs, files
in os.walk(node):
138 filename = os.path.join(root, f)
140 pattern_check =
reduce(
lambda x, y: x
or bool(fnmatch(filename, y)), file_patterns,
False)
141 exclude_check =
reduce(
lambda x, y: x
and fnmatch(filename, y), exclude_patterns,
True)
143 if pattern_check
and not exclude_check:
144 sources.append(filename)
146 for pattern
in file_patterns:
147 sources.extend(glob.glob(
"/".join([node, pattern])))
149 sources = map(
lambda path: env.File(path), sources )
153 def DoxySourceScanCheck(node, env):
154 """ Check if we should scan this file """ 155 return os.path.isfile(node.path)
158 def DoxyEmitter(source, target, env):
159 """ Doxygen Doxyfile emitter """ 162 "HTML": (
"YES",
"html"),
163 "LATEX": (
"YES",
"latex"),
164 "RTF": (
"NO",
"rtf"),
165 "MAN": (
"NO",
"man"),
166 "XML": (
"NO",
"xml"),
169 data = DoxyfileParse(source[0].get_contents())
172 out_dir = data.get(
"OUTPUT_DIRECTORY",
".")
175 for (k, v)
in output_formats.items():
176 if data.get(
"GENERATE_" + k, v[0]) ==
"YES":
177 targets.append(env.Dir( os.path.join(out_dir, data.get(k +
"_OUTPUT", v[1]))) )
185 env.Clean(node, node)
187 return (targets, source)
191 """ Add builders and construction variables for the 192 Doxygen tool. This is currently for Doxygen 1.4.6. 194 doxyfile_scanner = env.Scanner(
197 scan_check = DoxySourceScanCheck,
201 doxyfile_builder = SCons.Builder.Builder(
202 action =
"cd ${SOURCE.dir} && (${DOXYGEN} ${SOURCE.file} 2>&1 |tee ,doxylog)",
203 emitter = DoxyEmitter,
204 target_factory = env.fs.Entry,
205 single_source =
True,
206 source_scanner = doxyfile_scanner,
209 env.Append(BUILDERS = {
210 'Doxygen': doxyfile_builder,
219 """ Make sure doxygen exists. 221 return env.Detect(
"doxygen")