1#!/usr/bin/env python3 2 3# External command, intended to be called with custom_target(), 4# meson.add_install_script() or meson.add_dist_script() in meson.build. 5 6# argv[1] argv[2] argv[3:] 7# doc-reference.py <subcommand> <MMDOCTOOLDIR> <xxx>... 8 9# <MMDOCTOOLDIR> is an absolute path in the source directory. 10 11import os 12import sys 13import subprocess 14import shutil 15 16subcommand = sys.argv[1] 17MMDOCTOOLDIR = sys.argv[2] 18 19# Invoked from custom_target() in meson.build. 20def doxygen(): 21 # argv[3] argv[4:] 22 # <doxytagfile> <doc_input_files>... 23 24 # <doxytagfile> is a relative or absolute path in the build directory. 25 # <doc_input_files> are absolute paths in the source or build directory. 26 doxytagfile = sys.argv[3] 27 doc_outdir = os.path.dirname(doxytagfile) 28 29 # Export this variable for use in the Doxygen configuration file. 30 child_env = os.environ.copy() 31 child_env['MMDOCTOOLDIR'] = MMDOCTOOLDIR 32 33 # Remove old files. 34 if os.path.isfile(doxytagfile): 35 os.remove(doxytagfile) 36 shutil.rmtree(os.path.join(doc_outdir, 'html'), ignore_errors=True) 37 38 # Relative paths in Doxyfile assume that Doxygen is run from the 39 # build directory one level above Doxyfile. 40 doxygen_cwd = os.path.join(doc_outdir, '..') 41 42 DOXYGEN = child_env.get('DOXYGEN', None) 43 if not DOXYGEN: 44 DOXYGEN = 'doxygen' 45 doxygen_input = '@INCLUDE = ' + os.path.join('reference', 'Doxyfile') + '\n' \ 46 + 'INPUT = "' + '" "'.join(sys.argv[4:]) + '"\n' 47 # (Starting with Python 3.7 text=True is a more understandable equivalent to 48 # universal_newlines=True. Let's use only features in Python 3.5.) 49 result = subprocess.run([DOXYGEN, '-'], input=doxygen_input, 50 universal_newlines=True, env=child_env, cwd=doxygen_cwd) 51 if result.returncode: 52 return result.returncode 53 54 cmd = [ 55 'perl', 56 '--', 57 os.path.join(MMDOCTOOLDIR, 'doc-postprocess.pl'), 58 os.path.join(doc_outdir, 'html', '*.html'), 59 ] 60 return subprocess.run(cmd).returncode 61 62# Invoked from custom_target() in meson.build. 63def devhelp(): 64 # argv[3] argv[4] argv[5] argv[6] 65 # <doxytagfile> <devhelpfile> <book_name> <book_title> 66 67 # <doxytagfile> and <devhelpfile> are relative or absolute paths in the build directory. 68 doxytagfile = sys.argv[3] 69 devhelpfile = sys.argv[4] 70 book_name = sys.argv[5] 71 book_title = sys.argv[6] 72 tagfile_to_devhelp = os.path.join(MMDOCTOOLDIR, 'tagfile-to-devhelp2.xsl') 73 74 # The parameters to the Doxygen-to-Devhelp XSLT script. 75 cmd = [ 76 'xsltproc', 77 '--stringparam', 'book_title', book_title, 78 '--stringparam', 'book_name', book_name, 79 '--stringparam', 'book_base', 'html', 80 '-o', devhelpfile, 81 tagfile_to_devhelp, 82 doxytagfile, 83 ] 84 return subprocess.run(cmd).returncode 85 86# Invoked from meson.add_install_script(). 87def install_doc(): 88 # argv[3] argv[4] argv[5] argv[6:] 89 # <devhelpfile> <devhelpdir> <htmlrefdir> <docinstall_flags>... 90 91 # <devhelpfile> is a relative or absolute path in the build directory. 92 # <htmlrefdir> and <devhelpdir> are installation directories, relative to {prefix}. 93 devhelpfile = sys.argv[3] 94 destdir_devhelpdir = os.path.join(os.getenv('MESON_INSTALL_DESTDIR_PREFIX'), sys.argv[4]) 95 destdir_htmlrefdir = os.path.join(os.getenv('MESON_INSTALL_DESTDIR_PREFIX'), sys.argv[5]) 96 prefix_htmlrefdir = os.path.join(os.getenv('MESON_INSTALL_PREFIX'), sys.argv[5]) 97 build_dir = os.path.dirname(devhelpfile) 98 99 # Create the installation directories, if they do not exist. 100 os.makedirs(destdir_htmlrefdir, exist_ok=True) 101 os.makedirs(destdir_devhelpdir, exist_ok=True) 102 103 verbose = [] 104 if not os.getenv('MESON_INSTALL_QUIET'): 105 verbose = ['--verbose'] 106 107 # Install html files. 108 cmd = [ 109 'perl', 110 '--', 111 os.path.join(MMDOCTOOLDIR, 'doc-install.pl'), 112 '--mode=0644', 113 ] + verbose + sys.argv[6:] + [ 114 '-t', destdir_htmlrefdir, 115 '--glob', 116 '--', 117 os.path.join(build_dir, 'html', '*'), 118 ] 119 result1 = subprocess.run(cmd) 120 121 # Install the Devhelp file. 122 # rstrip('/') means remove trailing /, if any. 123 cmd = [ 124 'perl', 125 '--', 126 os.path.join(MMDOCTOOLDIR, 'doc-install.pl'), 127 '--mode=0644', 128 ] + verbose + [ 129 '--book-base=' + prefix_htmlrefdir.rstrip('/'), 130 '-t', destdir_devhelpdir, 131 '--', 132 devhelpfile, 133 ] 134 result2 = subprocess.run(cmd) 135 136 if result1.returncode: 137 return result1.returncode 138 return result2.returncode 139 140# Invoked from meson.add_dist_script(). 141def dist_doc(): 142 # argv[3] argv[4] argv[5] argv[6] 143 # <doctool_dist_dir> <doc_ref_build_dir> <tagfile> <devhelpfile> 144 145 # <doctool_dist_dir> is a distribution directory, relative to MESON_PROJECT_DIST_ROOT. 146 # <doc_ref_build_dir> is a relative or absolute path in the build directory. 147 # <tagfile> and <devhelpfile> are relative or absolute paths in the build directory. 148 149 # MESON_PROJECT_DIST_ROOT is set only if meson.version() >= 0.58.0. 150 project_dist_root = os.getenv('MESON_PROJECT_DIST_ROOT', os.getenv('MESON_DIST_ROOT')) 151 doctool_dist_dir = os.path.join(project_dist_root, sys.argv[3]) 152 doc_ref_build_dir = sys.argv[4] 153 tagfile = sys.argv[5] 154 devhelpfile = sys.argv[6] 155 156 # Create the distribution directory, if it does not exist. 157 os.makedirs(os.path.join(doctool_dist_dir, 'reference'), exist_ok=True) 158 159 # Distribute files that mm-common-get has copied to MMDOCTOOLDIR. 160 # shutil.copy() does not copy timestamps. 161 for file in ['doc-install.pl', 'doc-postprocess.pl', 'doxygen-extra.css', 'tagfile-to-devhelp2.xsl']: 162 shutil.copy(os.path.join(MMDOCTOOLDIR, file), doctool_dist_dir) 163 164 # Distribute built files: tag file, devhelp file, html files. 165 for file in [tagfile, devhelpfile]: 166 shutil.copy(file, os.path.join(doctool_dist_dir, 'reference')) 167 shutil.copytree(os.path.join(doc_ref_build_dir, 'html'), 168 os.path.join(doctool_dist_dir, 'reference', 'html'), 169 copy_function=shutil.copy) 170 return 0 171 172# ----- Main ----- 173if subcommand == 'doxygen': 174 sys.exit(doxygen()) 175if subcommand == 'devhelp': 176 sys.exit(devhelp()) 177if subcommand == 'install_doc': 178 sys.exit(install_doc()) 179if subcommand == 'dist_doc': 180 sys.exit(dist_doc()) 181print(sys.argv[0], ': illegal subcommand,', subcommand) 182sys.exit(1) 183