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