blob: 792bff78d9096044b47de06f02ddae38d729b067 [file] [log] [blame]
Baptiste Lepilleur57ee0e32010-02-22 04:16:10 +00001"""Script to generate doxygen documentation.
2"""
3
4import re
5import os
6import os.path
7import sys
8import shutil
Baptiste Lepilleure94d2f42010-02-23 21:00:30 +00009from devtools import tarball
Baptiste Lepilleur57ee0e32010-02-22 04:16:10 +000010
11def find_program(filename):
12 """find a program in folders path_lst, and sets env[var]
13 @param env: environmentA
14 @param filename: name of the program to search for
15 @param path_list: list of directories to search for filename
16 @param var: environment value to be checked for in env or os.environ
17 @return: either the value that is referenced with [var] in env or os.environ
18 or the first occurrence filename or '' if filename could not be found
19"""
20 paths = os.environ.get('PATH', '').split(os.pathsep)
21 suffixes = ('win32' in sys.platform ) and '.exe .com .bat .cmd' or ''
22 for name in [filename+ext for ext in suffixes.split()]:
23 for directory in paths:
24 full_path = os.path.join(directory, name)
25 if os.path.isfile(full_path):
26 return full_path
27 return ''
28
29def do_subst_in_file(targetfile, sourcefile, dict):
30 """Replace all instances of the keys of dict with their values.
31 For example, if dict is {'%VERSION%': '1.2345', '%BASE%': 'MyProg'},
32 then all instances of %VERSION% in the file will be replaced with 1.2345 etc.
33 """
34 try:
35 f = open(sourcefile, 'rb')
36 contents = f.read()
37 f.close()
38 except:
39 print "Can't read source file %s"%sourcefile
40 raise
41 for (k,v) in dict.items():
42 v = v.replace('\\','\\\\')
43 contents = re.sub(k, v, contents)
44 try:
45 f = open(targetfile, 'wb')
46 f.write(contents)
47 f.close()
48 except:
49 print "Can't write target file %s"%targetfile
50 raise
51
Baptiste Lepilleur1f4847c2010-02-23 07:57:38 +000052def run_doxygen(doxygen_path, config_file, working_dir, is_silent):
Baptiste Lepilleur57ee0e32010-02-22 04:16:10 +000053 config_file = os.path.abspath( config_file )
54 doxygen_path = doxygen_path
55 old_cwd = os.getcwd()
56 try:
57 os.chdir( working_dir )
58 cmd = [doxygen_path, config_file]
Baptiste Lepilleur1f4847c2010-02-23 07:57:38 +000059 print 'Running:', ' '.join( cmd )
Baptiste Lepilleur57ee0e32010-02-22 04:16:10 +000060 try:
61 import subprocess
62 except:
63 if os.system( ' '.join( cmd ) ) != 0:
64 print 'Documentation generation failed'
65 return False
66 else:
Baptiste Lepilleur1f4847c2010-02-23 07:57:38 +000067 if is_silent:
68 process = subprocess.Popen( cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT )
69 else:
70 process = subprocess.Popen( cmd )
71 stdout, _ = process.communicate()
72 if process.returncode:
73 print 'Documentation generation failed:'
74 print stdout
Baptiste Lepilleur57ee0e32010-02-22 04:16:10 +000075 return False
76 return True
77 finally:
78 os.chdir( old_cwd )
79
Baptiste Lepilleur1f4847c2010-02-23 07:57:38 +000080def build_doc( options, make_release=False ):
81 if make_release:
82 options.make_tarball = True
83 options.with_dot = True
84 options.with_html_help = True
85 options.with_uml_look = True
86 options.open = False
87 options.silent = True
Baptiste Lepilleur57ee0e32010-02-22 04:16:10 +000088
89 version = open('version','rt').read().strip()
90 output_dir = '../build/doxygen' # relative to doc/doxyfile location.
91 top_dir = os.path.abspath( '.' )
92 html_output_dirname = 'jsoncpp-api-html-' + version
93 tarball_path = os.path.join( 'dist', html_output_dirname + '.tar.gz' )
94 warning_log_path = os.path.join( output_dir, '../jsoncpp-doxygen-warning.log' )
95 def yesno( bool ):
96 return bool and 'YES' or 'NO'
97 subst_keys = {
98 '%JSONCPP_VERSION%': version,
99 '%DOC_TOPDIR%': '',
100 '%TOPDIR%': top_dir,
101 '%HTML_OUTPUT%': os.path.join( output_dir, html_output_dirname ),
102 '%HAVE_DOT%': yesno(options.with_dot),
103 '%DOT_PATH%': os.path.split(options.dot_path)[0],
104 '%HTML_HELP%': yesno(options.with_html_help),
105 '%UML_LOOK%': yesno(options.with_uml_look),
106 '%WARNING_LOG_PATH%': warning_log_path
107 }
108
109 full_output_dir = os.path.join( 'doc', output_dir )
110 if os.path.isdir( full_output_dir ):
111 print 'Deleting directory:', full_output_dir
112 shutil.rmtree( full_output_dir )
113 if not os.path.isdir( full_output_dir ):
114 os.makedirs( full_output_dir )
115
116 do_subst_in_file( 'doc/doxyfile', 'doc/doxyfile.in', subst_keys )
Baptiste Lepilleur1f4847c2010-02-23 07:57:38 +0000117 ok = run_doxygen( options.doxygen_path, 'doc/doxyfile', 'doc', is_silent=options.silent )
118 if not options.silent:
119 print open(os.path.join('doc', warning_log_path), 'rb').read()
Baptiste Lepilleur57ee0e32010-02-22 04:16:10 +0000120 index_path = os.path.abspath(os.path.join(subst_keys['%HTML_OUTPUT%'], 'index.html'))
121 print 'Generated documentation can be found in:'
122 print index_path
123 if options.open:
124 import webbrowser
125 webbrowser.open( 'file://' + index_path )
126 if options.make_tarball:
127 print 'Generating doc tarball to', tarball_path
128 tarball_sources = [
129 full_output_dir,
130 'README.txt',
131 'version'
132 ]
133 tarball_basedir = os.path.join( full_output_dir, html_output_dirname )
Baptiste Lepilleure94d2f42010-02-23 21:00:30 +0000134 tarball.make_tarball( tarball_path, tarball_sources, tarball_basedir, html_output_dirname )
Baptiste Lepilleur57ee0e32010-02-22 04:16:10 +0000135
Baptiste Lepilleur1f4847c2010-02-23 07:57:38 +0000136def main():
137 usage = """%prog
138 Generates doxygen documentation in build/doxygen.
139 Optionaly makes a tarball of the documentation to dist/.
140
141 Must be started in the project top directory.
142 """
143 from optparse import OptionParser
144 parser = OptionParser(usage=usage)
145 parser.allow_interspersed_args = False
146 parser.add_option('--with-dot', dest="with_dot", action='store_true', default=False,
147 help="""Enable usage of DOT to generate collaboration diagram""")
148 parser.add_option('--dot', dest="dot_path", action='store', default=find_program('dot'),
149 help="""Path to GraphViz dot tool. Must be full qualified path. [Default: %default]""")
150 parser.add_option('--doxygen', dest="doxygen_path", action='store', default=find_program('doxygen'),
151 help="""Path to Doxygen tool. [Default: %default]""")
152 parser.add_option('--with-html-help', dest="with_html_help", action='store_true', default=False,
153 help="""Enable generation of Microsoft HTML HELP""")
154 parser.add_option('--no-uml-look', dest="with_uml_look", action='store_false', default=True,
155 help="""Generates DOT graph without UML look [Default: False]""")
156 parser.add_option('--open', dest="open", action='store_true', default=False,
157 help="""Open the HTML index in the web browser after generation""")
158 parser.add_option('--tarball', dest="make_tarball", action='store_true', default=False,
159 help="""Generates a tarball of the documentation in dist/ directory""")
160 parser.add_option('-s', '--silent', dest="silent", action='store_true', default=False,
161 help="""Hides doxygen output""")
162 parser.enable_interspersed_args()
163 options, args = parser.parse_args()
164 build_doc( options )
165
Baptiste Lepilleur57ee0e32010-02-22 04:16:10 +0000166if __name__ == '__main__':
167 main()