mrobinson@webkit.org | 150f9cf | 2011-11-25 16:19:44 +0000 | [diff] [blame] | 1 | # Copyright (C) 2011 Igalia S.L. |
mrobinson@webkit.org | 59096b2 | 2011-11-10 03:00:43 +0000 | [diff] [blame] | 2 | # |
mrobinson@webkit.org | 150f9cf | 2011-11-25 16:19:44 +0000 | [diff] [blame] | 3 | # This library is free software; you can redistribute it and/or |
| 4 | # modify it under the terms of the GNU Lesser General Public |
| 5 | # License as published by the Free Software Foundation; either |
| 6 | # version 2 of the License, or (at your option) any later version. |
mrobinson@webkit.org | 59096b2 | 2011-11-10 03:00:43 +0000 | [diff] [blame] | 7 | # |
mrobinson@webkit.org | 150f9cf | 2011-11-25 16:19:44 +0000 | [diff] [blame] | 8 | # This library is distributed in the hope that it will be useful, |
| 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 11 | # Lesser General Public License for more details. |
mrobinson@webkit.org | 59096b2 | 2011-11-10 03:00:43 +0000 | [diff] [blame] | 12 | # |
mrobinson@webkit.org | 150f9cf | 2011-11-25 16:19:44 +0000 | [diff] [blame] | 13 | # You should have received a copy of the GNU Lesser General Public |
| 14 | # License along with this library; if not, write to the Free Software |
| 15 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
mrobinson@webkit.org | 59096b2 | 2011-11-10 03:00:43 +0000 | [diff] [blame] | 16 | |
carlosgc@webkit.org | 38ec27b | 2018-04-20 10:33:30 +0000 | [diff] [blame] | 17 | import codecs |
mrobinson@webkit.org | 59096b2 | 2011-11-10 03:00:43 +0000 | [diff] [blame] | 18 | import errno |
| 19 | import logging |
| 20 | import os |
| 21 | import os.path |
| 22 | import subprocess |
| 23 | import sys |
| 24 | |
| 25 | |
| 26 | class GTKDoc(object): |
| 27 | |
| 28 | """Class that controls a gtkdoc run. |
| 29 | |
| 30 | Each instance of this class represents one gtkdoc configuration |
| 31 | and set of documentation. The gtkdoc package is a series of tools |
| 32 | run consecutively which converts inline C/C++ documentation into |
| 33 | docbook files and then into HTML. This class is suitable for |
| 34 | generating documentation or simply verifying correctness. |
| 35 | |
| 36 | Keyword arguments: |
| 37 | output_dir -- The path where gtkdoc output should be placed. Generation |
| 38 | may overwrite file in this directory. Required. |
| 39 | module_name -- The name of the documentation module. For libraries this |
| 40 | is typically the library name. Required if not library path |
| 41 | is given. |
mrobinson@webkit.org | 231f2a0 | 2014-02-25 07:30:21 +0000 | [diff] [blame] | 42 | source_dirs -- A list of paths to directories of source code to be scanned. |
| 43 | Required if headers is not specified. |
mrobinson@webkit.org | 59096b2 | 2011-11-10 03:00:43 +0000 | [diff] [blame] | 44 | ignored_files -- A list of filenames to ignore in the source directory. It is |
| 45 | only necessary to provide the basenames of these files. |
| 46 | Typically it is important to provide an updated list of |
| 47 | ignored files to prevent warnings about undocumented symbols. |
mrobinson@webkit.org | 231f2a0 | 2014-02-25 07:30:21 +0000 | [diff] [blame] | 48 | headers -- A list of paths to headers to be scanned. Required if source_dirs |
| 49 | is not specified. |
carlosgc@webkit.org | f4dfe8e | 2013-11-08 08:12:09 +0000 | [diff] [blame] | 50 | namespace -- The library namespace. |
mrobinson@webkit.org | 59096b2 | 2011-11-10 03:00:43 +0000 | [diff] [blame] | 51 | decorator -- If a decorator is used to unhide certain symbols in header |
| 52 | files this parameter is required for successful scanning. |
| 53 | (default '') |
| 54 | deprecation_guard -- gtkdoc tries to ensure that symbols marked as deprecated |
| 55 | are encased in this C preprocessor define. This is required |
| 56 | to avoid gtkdoc warnings. (default '') |
| 57 | cflags -- This parameter specifies any preprocessor flags necessary for |
| 58 | building the scanner binary during gtkdoc-scanobj. Typically |
| 59 | this includes all absolute include paths necessary to resolve |
| 60 | all header dependencies. (default '') |
| 61 | ldflags -- This parameter specifies any linker flags necessary for |
| 62 | building the scanner binary during gtkdoc-scanobj. Typically |
| 63 | this includes "-lyourlibraryname". (default '') |
| 64 | library_path -- This parameter specifies the path to the directory where you |
| 65 | library resides used for building the scanner binary during |
| 66 | gtkdoc-scanobj. (default '') |
| 67 | |
| 68 | doc_dir -- The path to other documentation files necessary to build |
| 69 | the documentation. This files in this directory as well as |
| 70 | the files in the 'html' subdirectory will be copied |
| 71 | recursively into the output directory. (default '') |
| 72 | main_sgml_file -- The path or name (if a doc_dir is given) of the SGML file |
| 73 | that is the considered the main page of your documentation. |
| 74 | (default: <module_name>-docs.sgml) |
| 75 | version -- The version number of the module. If this is provided, |
| 76 | a version.xml file containing the version will be created |
| 77 | in the output directory during documentation generation. |
| 78 | |
| 79 | interactive -- Whether or not errors or warnings should prompt the user |
| 80 | to continue or not. When this value is false, generation |
| 81 | will continue despite warnings. (default False) |
kov@webkit.org | 316a907 | 2012-02-09 02:28:31 +0000 | [diff] [blame] | 82 | |
| 83 | virtual_root -- A temporary installation directory which is used as the root |
| 84 | where the actual installation prefix lives; this is mostly |
| 85 | useful for packagers, and should be set to what is given to |
| 86 | make install as DESTDIR. |
mrobinson@webkit.org | 59096b2 | 2011-11-10 03:00:43 +0000 | [diff] [blame] | 87 | """ |
| 88 | |
carlosgc@webkit.org | 7bd5597 | 2012-02-01 18:04:57 +0000 | [diff] [blame] | 89 | def __init__(self, args): |
mrobinson@webkit.org | 59096b2 | 2011-11-10 03:00:43 +0000 | [diff] [blame] | 90 | |
| 91 | # Parameters specific to scanning. |
| 92 | self.module_name = '' |
| 93 | self.source_dirs = [] |
mrobinson@webkit.org | 231f2a0 | 2014-02-25 07:30:21 +0000 | [diff] [blame] | 94 | self.headers = [] |
mrobinson@webkit.org | 59096b2 | 2011-11-10 03:00:43 +0000 | [diff] [blame] | 95 | self.ignored_files = [] |
carlosgc@webkit.org | f4dfe8e | 2013-11-08 08:12:09 +0000 | [diff] [blame] | 96 | self.namespace = '' |
mrobinson@webkit.org | 59096b2 | 2011-11-10 03:00:43 +0000 | [diff] [blame] | 97 | self.decorator = '' |
| 98 | self.deprecation_guard = '' |
| 99 | |
| 100 | # Parameters specific to gtkdoc-scanobj. |
| 101 | self.cflags = '' |
| 102 | self.ldflags = '' |
| 103 | self.library_path = '' |
| 104 | |
| 105 | # Parameters specific to generation. |
| 106 | self.output_dir = '' |
| 107 | self.doc_dir = '' |
| 108 | self.main_sgml_file = '' |
| 109 | |
carlosgc@webkit.org | a5df539 | 2012-02-06 09:23:08 +0000 | [diff] [blame] | 110 | # Parameters specific to gtkdoc-fixxref. |
| 111 | self.cross_reference_deps = [] |
| 112 | |
mrobinson@webkit.org | 59096b2 | 2011-11-10 03:00:43 +0000 | [diff] [blame] | 113 | self.interactive = False |
| 114 | |
| 115 | self.logger = logging.getLogger('gtkdoc') |
| 116 | |
zandobersek@gmail.com | d23a5a1 | 2013-01-08 10:10:24 +0000 | [diff] [blame] | 117 | for key, value in iter(args.items()): |
mrobinson@webkit.org | 59096b2 | 2011-11-10 03:00:43 +0000 | [diff] [blame] | 118 | setattr(self, key, value) |
| 119 | |
mrobinson@webkit.org | 231f2a0 | 2014-02-25 07:30:21 +0000 | [diff] [blame] | 120 | if not getattr(self, 'output_dir'): |
| 121 | raise Exception('output_dir not specified.') |
| 122 | if not getattr(self, 'module_name'): |
| 123 | raise Exception('module_name not specified.') |
| 124 | if not getattr(self, 'source_dirs') and not getattr(self, 'headers'): |
| 125 | raise Exception('Neither source_dirs nor headers specified.' % key) |
mrobinson@webkit.org | 59096b2 | 2011-11-10 03:00:43 +0000 | [diff] [blame] | 126 | |
| 127 | # Make all paths absolute in case we were passed relative paths, since |
| 128 | # we change the current working directory when executing subcommands. |
| 129 | self.output_dir = os.path.abspath(self.output_dir) |
| 130 | self.source_dirs = [os.path.abspath(x) for x in self.source_dirs] |
mrobinson@webkit.org | 231f2a0 | 2014-02-25 07:30:21 +0000 | [diff] [blame] | 131 | self.headers = [os.path.abspath(x) for x in self.headers] |
mrobinson@webkit.org | 59096b2 | 2011-11-10 03:00:43 +0000 | [diff] [blame] | 132 | if self.library_path: |
| 133 | self.library_path = os.path.abspath(self.library_path) |
| 134 | |
| 135 | if not self.main_sgml_file: |
| 136 | self.main_sgml_file = self.module_name + "-docs.sgml" |
| 137 | |
| 138 | def generate(self, html=True): |
| 139 | self.saw_warnings = False |
| 140 | |
| 141 | self._copy_doc_files_to_output_dir(html) |
| 142 | self._write_version_xml() |
| 143 | self._run_gtkdoc_scan() |
| 144 | self._run_gtkdoc_scangobj() |
mrobinson@webkit.org | 59096b2 | 2011-11-10 03:00:43 +0000 | [diff] [blame] | 145 | self._run_gtkdoc_mkdb() |
| 146 | |
| 147 | if not html: |
| 148 | return |
| 149 | |
| 150 | self._run_gtkdoc_mkhtml() |
| 151 | self._run_gtkdoc_fixxref() |
| 152 | |
| 153 | def _delete_file_if_exists(self, path): |
| 154 | if not os.access(path, os.F_OK | os.R_OK): |
| 155 | return |
| 156 | self.logger.debug('deleting %s', path) |
| 157 | os.unlink(path) |
| 158 | |
| 159 | def _create_directory_if_nonexistent(self, path): |
| 160 | try: |
| 161 | os.makedirs(path) |
| 162 | except OSError as error: |
| 163 | if error.errno != errno.EEXIST: |
| 164 | raise |
| 165 | |
| 166 | def _raise_exception_if_file_inaccessible(self, path): |
| 167 | if not os.path.exists(path) or not os.access(path, os.R_OK): |
| 168 | raise Exception("Could not access file at: %s" % path) |
| 169 | |
| 170 | def _output_has_warnings(self, outputs): |
| 171 | for output in outputs: |
| 172 | if output and output.find('warning'): |
| 173 | return True |
| 174 | return False |
| 175 | |
| 176 | def _ask_yes_or_no_question(self, question): |
| 177 | if not self.interactive: |
| 178 | return True |
| 179 | |
| 180 | question += ' [y/N] ' |
| 181 | answer = None |
| 182 | while answer != 'y' and answer != 'n' and answer != '': |
| 183 | answer = raw_input(question).lower() |
| 184 | return answer == 'y' |
| 185 | |
carlosgc@webkit.org | 0145461 | 2017-01-21 10:21:33 +0000 | [diff] [blame] | 186 | def _run_command(self, args, env=None, cwd=None, print_output=True, ignore_warnings=False): |
mrobinson@webkit.org | 150f9cf | 2011-11-25 16:19:44 +0000 | [diff] [blame] | 187 | if print_output: |
carlosgc@webkit.org | 0145461 | 2017-01-21 10:21:33 +0000 | [diff] [blame] | 188 | self.logger.debug("Running %s", args[0]) |
mrobinson@webkit.org | 59096b2 | 2011-11-10 03:00:43 +0000 | [diff] [blame] | 189 | self.logger.debug("Full command args: %s", str(args)) |
| 190 | |
| 191 | process = subprocess.Popen(args, env=env, cwd=cwd, |
| 192 | stdout=subprocess.PIPE, |
| 193 | stderr=subprocess.PIPE) |
zandobersek@gmail.com | d23a5a1 | 2013-01-08 10:10:24 +0000 | [diff] [blame] | 194 | stdout, stderr = [b.decode("utf-8") for b in process.communicate()] |
mrobinson@webkit.org | 59096b2 | 2011-11-10 03:00:43 +0000 | [diff] [blame] | 195 | |
| 196 | if print_output: |
| 197 | if stdout: |
carlosgc@webkit.org | 7ebab88 | 2014-10-04 07:35:47 +0000 | [diff] [blame] | 198 | try: |
| 199 | sys.stdout.write(stdout.encode("utf-8")) |
| 200 | except UnicodeDecodeError: |
| 201 | sys.stdout.write(stdout) |
mrobinson@webkit.org | 59096b2 | 2011-11-10 03:00:43 +0000 | [diff] [blame] | 202 | if stderr: |
carlosgc@webkit.org | 7ebab88 | 2014-10-04 07:35:47 +0000 | [diff] [blame] | 203 | try: |
| 204 | sys.stderr.write(stderr.encode("utf-8")) |
| 205 | except UnicodeDecodeError: |
| 206 | sys.stderr.write(stderr) |
mrobinson@webkit.org | 59096b2 | 2011-11-10 03:00:43 +0000 | [diff] [blame] | 207 | |
| 208 | if process.returncode != 0: |
| 209 | raise Exception('%s produced a non-zero return code %i' |
| 210 | % (args[0], process.returncode)) |
| 211 | |
mrobinson@webkit.org | 150f9cf | 2011-11-25 16:19:44 +0000 | [diff] [blame] | 212 | if not ignore_warnings and ('warning' in stderr or 'warning' in stdout): |
mrobinson@webkit.org | 59096b2 | 2011-11-10 03:00:43 +0000 | [diff] [blame] | 213 | self.saw_warnings = True |
| 214 | if not self._ask_yes_or_no_question('%s produced warnings, ' |
| 215 | 'try to continue?' % args[0]): |
| 216 | raise Exception('%s step failed' % args[0]) |
| 217 | |
| 218 | return stdout.strip() |
| 219 | |
| 220 | def _copy_doc_files_to_output_dir(self, html=True): |
| 221 | if not self.doc_dir: |
| 222 | self.logger.info('Not copying any files from doc directory,' |
| 223 | ' because no doc directory given.') |
| 224 | return |
| 225 | |
| 226 | def copy_file_replacing_existing(src, dest): |
| 227 | if os.path.isdir(src): |
| 228 | self.logger.debug('skipped directory %s', src) |
| 229 | return |
| 230 | if not os.access(src, os.F_OK | os.R_OK): |
| 231 | self.logger.debug('skipped unreadable %s', src) |
| 232 | return |
| 233 | |
| 234 | self._delete_file_if_exists(dest) |
| 235 | |
| 236 | self.logger.debug('created %s', dest) |
berto@igalia.com | ac25f33 | 2013-09-14 18:03:40 +0000 | [diff] [blame] | 237 | try: |
| 238 | os.link(src, dest) |
| 239 | except OSError: |
| 240 | os.symlink(src, dest) |
mrobinson@webkit.org | 59096b2 | 2011-11-10 03:00:43 +0000 | [diff] [blame] | 241 | |
| 242 | def copy_all_files_in_directory(src, dest): |
| 243 | for path in os.listdir(src): |
| 244 | copy_file_replacing_existing(os.path.join(src, path), |
| 245 | os.path.join(dest, path)) |
| 246 | |
mcatanzaro@igalia.com | 0389b67 | 2016-12-19 13:02:54 +0000 | [diff] [blame] | 247 | self.logger.debug('Copying template files to output directory...') |
mrobinson@webkit.org | 59096b2 | 2011-11-10 03:00:43 +0000 | [diff] [blame] | 248 | self._create_directory_if_nonexistent(self.output_dir) |
| 249 | copy_all_files_in_directory(self.doc_dir, self.output_dir) |
| 250 | |
mrobinson@webkit.org | 59096b2 | 2011-11-10 03:00:43 +0000 | [diff] [blame] | 251 | def _write_version_xml(self): |
| 252 | if not self.version: |
| 253 | self.logger.info('No version specified, so not writing version.xml') |
| 254 | return |
| 255 | |
| 256 | version_xml_path = os.path.join(self.output_dir, 'version.xml') |
| 257 | src_version_xml_path = os.path.join(self.doc_dir, 'version.xml') |
| 258 | |
| 259 | # Don't overwrite version.xml if it was in the doc directory. |
| 260 | if os.path.exists(version_xml_path) and \ |
| 261 | os.path.exists(src_version_xml_path): |
| 262 | return |
| 263 | |
| 264 | output_file = open(version_xml_path, 'w') |
| 265 | output_file.write(self.version) |
| 266 | output_file.close() |
| 267 | |
carlosgc@webkit.org | 76c235d | 2012-02-06 09:29:34 +0000 | [diff] [blame] | 268 | def _ignored_files_basenames(self): |
| 269 | return ' '.join([os.path.basename(x) for x in self.ignored_files]) |
| 270 | |
mrobinson@webkit.org | 59096b2 | 2011-11-10 03:00:43 +0000 | [diff] [blame] | 271 | def _run_gtkdoc_scan(self): |
| 272 | args = ['gtkdoc-scan', |
| 273 | '--module=%s' % self.module_name, |
| 274 | '--rebuild-types'] |
| 275 | |
mrobinson@webkit.org | 231f2a0 | 2014-02-25 07:30:21 +0000 | [diff] [blame] | 276 | if not self.headers: |
| 277 | # Each source directory should be have its own "--source-dir=" prefix. |
| 278 | args.extend(['--source-dir=%s' % path for path in self.source_dirs]) |
mrobinson@webkit.org | 59096b2 | 2011-11-10 03:00:43 +0000 | [diff] [blame] | 279 | |
| 280 | if self.decorator: |
| 281 | args.append('--ignore-decorators=%s' % self.decorator) |
| 282 | if self.deprecation_guard: |
| 283 | args.append('--deprecated-guards=%s' % self.deprecation_guard) |
| 284 | if self.output_dir: |
| 285 | args.append('--output-dir=%s' % self.output_dir) |
| 286 | |
mrobinson@webkit.org | 231f2a0 | 2014-02-25 07:30:21 +0000 | [diff] [blame] | 287 | # We only need to pass the list of ignored files if the we are not using an explicit list of headers. |
| 288 | if not self.headers: |
| 289 | # gtkdoc-scan wants the basenames of ignored headers, so strip the |
| 290 | # dirname. Different from "--source-dir", the headers should be |
| 291 | # specified as one long string. |
| 292 | ignored_files_basenames = self._ignored_files_basenames() |
| 293 | if ignored_files_basenames: |
| 294 | args.append('--ignore-headers=%s' % ignored_files_basenames) |
| 295 | |
| 296 | if self.headers: |
| 297 | args.extend(self.headers) |
mrobinson@webkit.org | 59096b2 | 2011-11-10 03:00:43 +0000 | [diff] [blame] | 298 | |
| 299 | self._run_command(args) |
| 300 | |
| 301 | def _run_gtkdoc_scangobj(self): |
| 302 | env = os.environ |
| 303 | ldflags = self.ldflags |
| 304 | if self.library_path: |
commit-queue@webkit.org | 77ff950 | 2014-11-17 10:48:39 +0000 | [diff] [blame] | 305 | additional_ldflags = '' |
| 306 | for arg in env.get('LDFLAGS', '').split(' '): |
| 307 | if arg.startswith('-L'): |
| 308 | additional_ldflags = '%s %s' % (additional_ldflags, arg) |
| 309 | ldflags = ' "-L%s" %s ' % (self.library_path, additional_ldflags) + ldflags |
mrobinson@webkit.org | 150f9cf | 2011-11-25 16:19:44 +0000 | [diff] [blame] | 310 | current_ld_library_path = env.get('LD_LIBRARY_PATH') |
| 311 | if current_ld_library_path: |
mcatanzaro@igalia.com | bdb85f4 | 2017-11-04 16:47:46 +0000 | [diff] [blame] | 312 | env['LD_LIBRARY_PATH'] = '%s:%s' % (self.library_path, current_ld_library_path) |
mrobinson@webkit.org | 150f9cf | 2011-11-25 16:19:44 +0000 | [diff] [blame] | 313 | else: |
mcatanzaro@igalia.com | bdb85f4 | 2017-11-04 16:47:46 +0000 | [diff] [blame] | 314 | env['LD_LIBRARY_PATH'] = self.library_path |
mrobinson@webkit.org | 150f9cf | 2011-11-25 16:19:44 +0000 | [diff] [blame] | 315 | |
mrobinson@webkit.org | 59096b2 | 2011-11-10 03:00:43 +0000 | [diff] [blame] | 316 | if ldflags: |
carlosgc@webkit.org | 9437061 | 2012-01-16 12:19:41 +0000 | [diff] [blame] | 317 | env['LDFLAGS'] = '%s %s' % (ldflags, env.get('LDFLAGS', '')) |
mrobinson@webkit.org | 59096b2 | 2011-11-10 03:00:43 +0000 | [diff] [blame] | 318 | if self.cflags: |
carlosgc@webkit.org | 9437061 | 2012-01-16 12:19:41 +0000 | [diff] [blame] | 319 | env['CFLAGS'] = '%s %s' % (self.cflags, env.get('CFLAGS', '')) |
mrobinson@webkit.org | 59096b2 | 2011-11-10 03:00:43 +0000 | [diff] [blame] | 320 | |
| 321 | if 'CFLAGS' in env: |
| 322 | self.logger.debug('CFLAGS=%s', env['CFLAGS']) |
| 323 | if 'LDFLAGS' in env: |
| 324 | self.logger.debug('LDFLAGS %s', env['LDFLAGS']) |
mrobinson@webkit.org | 59096b2 | 2011-11-10 03:00:43 +0000 | [diff] [blame] | 325 | self._run_command(['gtkdoc-scangobj', '--module=%s' % self.module_name], |
| 326 | env=env, cwd=self.output_dir) |
| 327 | |
mrobinson@webkit.org | 59096b2 | 2011-11-10 03:00:43 +0000 | [diff] [blame] | 328 | def _run_gtkdoc_mkdb(self): |
| 329 | sgml_file = os.path.join(self.output_dir, self.main_sgml_file) |
| 330 | self._raise_exception_if_file_inaccessible(sgml_file) |
| 331 | |
| 332 | args = ['gtkdoc-mkdb', |
| 333 | '--module=%s' % self.module_name, |
| 334 | '--main-sgml-file=%s' % sgml_file, |
| 335 | '--source-suffixes=h,c,cpp,cc', |
| 336 | '--output-format=xml', |
| 337 | '--sgml-mode'] |
| 338 | |
carlosgc@webkit.org | f4dfe8e | 2013-11-08 08:12:09 +0000 | [diff] [blame] | 339 | if self.namespace: |
| 340 | args.append('--name-space=%s' % self.namespace) |
| 341 | |
carlosgc@webkit.org | 76c235d | 2012-02-06 09:29:34 +0000 | [diff] [blame] | 342 | ignored_files_basenames = self._ignored_files_basenames() |
| 343 | if ignored_files_basenames: |
| 344 | args.append('--ignore-files=%s' % ignored_files_basenames) |
| 345 | |
mrobinson@webkit.org | 59096b2 | 2011-11-10 03:00:43 +0000 | [diff] [blame] | 346 | # Each directory should be have its own "--source-dir=" prefix. |
| 347 | args.extend(['--source-dir=%s' % path for path in self.source_dirs]) |
| 348 | self._run_command(args, cwd=self.output_dir) |
| 349 | |
| 350 | def _run_gtkdoc_mkhtml(self): |
carlosgc@webkit.org | 38ec27b | 2018-04-20 10:33:30 +0000 | [diff] [blame] | 351 | # gtkdoc-fixxref expects the paths to be html/modulename. |
| 352 | html_dest_dir = os.path.join(self.output_dir, 'html', self.module_name) |
| 353 | self._create_directory_if_nonexistent(html_dest_dir) |
mrobinson@webkit.org | 59096b2 | 2011-11-10 03:00:43 +0000 | [diff] [blame] | 354 | if not os.path.isdir(html_dest_dir): |
| 355 | raise Exception("%s is not a directory, could not generate HTML" |
| 356 | % html_dest_dir) |
| 357 | elif not os.access(html_dest_dir, os.X_OK | os.R_OK | os.W_OK): |
| 358 | raise Exception("Could not access %s to generate HTML" |
| 359 | % html_dest_dir) |
| 360 | |
| 361 | # gtkdoc-mkhtml expects the SGML path to be absolute. |
| 362 | sgml_file = os.path.join(os.path.abspath(self.output_dir), |
| 363 | self.main_sgml_file) |
| 364 | self._raise_exception_if_file_inaccessible(sgml_file) |
| 365 | |
| 366 | self._run_command(['gtkdoc-mkhtml', self.module_name, sgml_file], |
| 367 | cwd=html_dest_dir) |
| 368 | |
| 369 | def _run_gtkdoc_fixxref(self): |
carlosgc@webkit.org | a5df539 | 2012-02-06 09:23:08 +0000 | [diff] [blame] | 370 | args = ['gtkdoc-fixxref', |
commit-queue@webkit.org | 4231b20 | 2017-05-20 19:56:40 +0000 | [diff] [blame] | 371 | '--module=%s' % self.module_name, |
carlosgc@webkit.org | 38ec27b | 2018-04-20 10:33:30 +0000 | [diff] [blame] | 372 | '--module-dir=html/%s' % self.module_name] |
carlosgc@webkit.org | a5df539 | 2012-02-06 09:23:08 +0000 | [diff] [blame] | 373 | args.extend(['--extra-dir=%s' % extra_dir for extra_dir in self.cross_reference_deps]) |
| 374 | self._run_command(args, cwd=self.output_dir, ignore_warnings=True) |
| 375 | |
carlosgc@webkit.org | 38ec27b | 2018-04-20 10:33:30 +0000 | [diff] [blame] | 376 | # gtkdoc-fixxref has some predefined links for which it always uses absolute paths. |
| 377 | html_dir_prefix = os.path.join(self.virtual_root + self.prefix, 'share', 'gtk-doc', 'html') |
| 378 | module_dir = os.path.join(self.output_dir, 'html', self.module_name) |
| 379 | for entry in os.listdir(module_dir): |
| 380 | if not entry.endswith('.html'): |
| 381 | continue |
| 382 | |
| 383 | filename = os.path.join(module_dir, entry) |
| 384 | contents = '' |
| 385 | with codecs.open(filename, 'r', encoding='utf-8') as f: |
| 386 | contents = f.read() |
| 387 | |
| 388 | if not html_dir_prefix in contents: |
| 389 | continue |
| 390 | |
| 391 | tmp_filename = filename + '.new' |
| 392 | new_contents = contents.replace(html_dir_prefix, '..') |
| 393 | with codecs.open(tmp_filename, 'w', encoding='utf-8') as f: |
| 394 | f.write(new_contents) |
| 395 | |
| 396 | os.rename(tmp_filename, filename) |
| 397 | |
carlosgc@webkit.org | a5df539 | 2012-02-06 09:23:08 +0000 | [diff] [blame] | 398 | def rebase_installed_docs(self): |
commit-queue@webkit.org | 0b33847 | 2012-09-04 18:33:10 +0000 | [diff] [blame] | 399 | if not os.path.isdir(self.output_dir): |
| 400 | raise Exception("Tried to rebase documentation before generating it.") |
kov@webkit.org | 316a907 | 2012-02-09 02:28:31 +0000 | [diff] [blame] | 401 | html_dir = os.path.join(self.virtual_root + self.prefix, 'share', 'gtk-doc', 'html', self.module_name) |
carlosgc@webkit.org | 0313edc | 2012-02-06 14:54:38 +0000 | [diff] [blame] | 402 | if not os.path.isdir(html_dir): |
| 403 | return |
carlosgc@webkit.org | a5df539 | 2012-02-06 09:23:08 +0000 | [diff] [blame] | 404 | args = ['gtkdoc-rebase', |
| 405 | '--relative', |
| 406 | '--html-dir=%s' % html_dir] |
| 407 | args.extend(['--other-dir=%s' % extra_dir for extra_dir in self.cross_reference_deps]) |
kov@webkit.org | 316a907 | 2012-02-09 02:28:31 +0000 | [diff] [blame] | 408 | if self.virtual_root: |
| 409 | args.extend(['--dest-dir=%s' % self.virtual_root]) |
carlosgc@webkit.org | a5df539 | 2012-02-06 09:23:08 +0000 | [diff] [blame] | 410 | self._run_command(args, cwd=self.output_dir) |
mrobinson@webkit.org | 59096b2 | 2011-11-10 03:00:43 +0000 | [diff] [blame] | 411 | |
commit-queue@webkit.org | 0b33847 | 2012-09-04 18:33:10 +0000 | [diff] [blame] | 412 | def api_missing_documentation(self): |
| 413 | unused_doc_file = os.path.join(self.output_dir, self.module_name + "-unused.txt") |
| 414 | if not os.path.exists(unused_doc_file) or not os.access(unused_doc_file, os.R_OK): |
| 415 | return [] |
| 416 | return open(unused_doc_file).read().splitlines() |
mrobinson@webkit.org | 59096b2 | 2011-11-10 03:00:43 +0000 | [diff] [blame] | 417 | |
| 418 | class PkgConfigGTKDoc(GTKDoc): |
| 419 | |
| 420 | """Class reads a library's pkgconfig file to guess gtkdoc parameters. |
| 421 | |
| 422 | Some gtkdoc parameters can be guessed by reading a library's pkgconfig |
| 423 | file, including the cflags, ldflags and version parameters. If you |
| 424 | provide these parameters as well, they will be appended to the ones |
| 425 | guessed via the pkgconfig file. |
| 426 | |
| 427 | Keyword arguments: |
| 428 | pkg_config_path -- Path to the pkgconfig file for the library. Required. |
| 429 | """ |
| 430 | |
carlosgc@webkit.org | 7bd5597 | 2012-02-01 18:04:57 +0000 | [diff] [blame] | 431 | def __init__(self, pkg_config_path, args): |
| 432 | super(PkgConfigGTKDoc, self).__init__(args) |
mrobinson@webkit.org | 59096b2 | 2011-11-10 03:00:43 +0000 | [diff] [blame] | 433 | |
commit-queue@webkit.org | 5c6df64 | 2013-06-03 22:25:19 +0000 | [diff] [blame] | 434 | pkg_config = os.environ.get('PKG_CONFIG', 'pkg-config') |
| 435 | |
mrobinson@webkit.org | 59096b2 | 2011-11-10 03:00:43 +0000 | [diff] [blame] | 436 | if not os.path.exists(pkg_config_path): |
| 437 | raise Exception('Could not find pkg-config file at: %s' |
| 438 | % pkg_config_path) |
| 439 | |
commit-queue@webkit.org | 5c6df64 | 2013-06-03 22:25:19 +0000 | [diff] [blame] | 440 | self.cflags += " " + self._run_command([pkg_config, |
mrobinson@webkit.org | 59096b2 | 2011-11-10 03:00:43 +0000 | [diff] [blame] | 441 | pkg_config_path, |
| 442 | '--cflags'], print_output=False) |
commit-queue@webkit.org | 5c6df64 | 2013-06-03 22:25:19 +0000 | [diff] [blame] | 443 | self.ldflags += " " + self._run_command([pkg_config, |
mrobinson@webkit.org | 59096b2 | 2011-11-10 03:00:43 +0000 | [diff] [blame] | 444 | pkg_config_path, |
| 445 | '--libs'], print_output=False) |
commit-queue@webkit.org | 5c6df64 | 2013-06-03 22:25:19 +0000 | [diff] [blame] | 446 | self.version = self._run_command([pkg_config, |
mrobinson@webkit.org | 59096b2 | 2011-11-10 03:00:43 +0000 | [diff] [blame] | 447 | pkg_config_path, |
| 448 | '--modversion'], print_output=False) |
commit-queue@webkit.org | 5c6df64 | 2013-06-03 22:25:19 +0000 | [diff] [blame] | 449 | self.prefix = self._run_command([pkg_config, |
carlosgc@webkit.org | a5df539 | 2012-02-06 09:23:08 +0000 | [diff] [blame] | 450 | pkg_config_path, |
| 451 | '--variable=prefix'], print_output=False) |