Added: trunk/Source/WebKit2/UIProcess/API/gtk/docs/build-gtkdoc (0 => 99802)
--- trunk/Source/WebKit2/UIProcess/API/gtk/docs/build-gtkdoc (rev 0)
+++ trunk/Source/WebKit2/UIProcess/API/gtk/docs/build-gtkdoc 2011-11-10 03:00:43 UTC (rev 99802)
@@ -0,0 +1,93 @@
+#!/usr/bin/env python
+# Copyright (C) 2011 Igalia S.L.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+#
+
+import glob
+import gtkdoc
+import logging
+import os.path
+import sys
+
+def configure_logging():
+ level = logging.DEBUG if '-v' in sys.argv else logging.INFO
+ logger = logging.getLogger("gtkdoc")
+ logger.setLevel(level)
+ handler = logging.StreamHandler()
+ handler.setLevel(level)
+ logger.addHandler(handler)
+ if level == logging.DEBUG:
+ handler.setFormatter(logging.Formatter('[%(asctime)s] %(message)s'))
+ else:
+ handler.setFormatter(logging.Formatter('%(message)s'))
+
+def find_build_directory(top_level):
+ def is_valid_build_directory(build_dir):
+ return os.path.exists(os.path.join(build_dir, ".libs"))
+
+ if is_valid_build_directory(top_level):
+ return top_level
+
+ build_dir = os.path.join(top_level, 'WebKitBuild')
+ if is_valid_build_directory(build_dir):
+ return build_dir
+
+ build_dir = os.path.join(top_level, 'WebKitBuild', 'Release')
+ if is_valid_build_directory(build_dir):
+ return build_dir
+
+ build_dir = os.path.join(top_level, 'WebKitBuild', 'Debug')
+ if is_valid_build_directory(build_dir):
+ return build_dir
+ print "Could not determine build directory."
+ sys.exit(1)
+
+doc_dir = os.path.abspath(os.path.dirname(__file__))
+top_level = os.path.normpath(os.path.join(doc_dir, '..', '..',
+ '..', '..', '..', '..'))
+build_dir = find_build_directory(top_level)
+
+output_dir = os.path.join(build_dir, "Documentation", "webkit2gtk")
+src_dir = os.path.join(doc_dir, '..')
+library_path = os.path.join(build_dir, ".libs")
+pkg_config_path = \
+ os.path.join(build_dir, "Source", "WebKit2", "webkit2gtk-3.0.pc")
+
+derived_sources = os.path.join(build_dir, "DerivedSources", "WebKit2")
+cflags = \
+' -I' + os.path.join(derived_sources, 'webkit2gtk', 'include') + \
+' -I' + os.path.join(derived_sources, 'webkit2gtk') + \
+' -I' + os.path.join(derived_sources, 'include') + \
+' -I' + os.path.join(top_level, 'Source')
+' -I' + src_dir
+
+ignored_files = glob.glob("%s/*Private.h" % src_dir) + \
+ glob.glob("%s/PageClientImpl.*" % src_dir) + \
+ glob.glob("%s/tests/*.h" % src_dir)
+
+configure_logging()
+generator = gtkdoc.PkgConfigGTKDoc(pkg_config_path,
+ module_name="webkit2gtk",
+ output_dir=output_dir,
+ source_dirs=[src_dir],
+ doc_dir=doc_dir,
+ cflags=cflags,
+ library_path=library_path,
+ decorator="WEBKIT_API",
+ deprecation_guard="WEBKIT_DISABLE_DEPRECATED",
+ ignored_files=ignored_files)
+generator.generate(html='--skip-html' not in sys.argv)
+sys.exit(generator.saw_warnings)
Property changes on: trunk/Source/WebKit2/UIProcess/API/gtk/docs/build-gtkdoc
___________________________________________________________________
Added: trunk/Source/WebKit2/UIProcess/API/gtk/docs/gtkdoc.py (0 => 99802)
--- trunk/Source/WebKit2/UIProcess/API/gtk/docs/gtkdoc.py (rev 0)
+++ trunk/Source/WebKit2/UIProcess/API/gtk/docs/gtkdoc.py 2011-11-10 03:00:43 UTC (rev 99802)
@@ -0,0 +1,372 @@
+# Copyright (C) 2011 Igalia S.L.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+#
+
+import errno
+import logging
+import os
+import os.path
+import subprocess
+import sys
+
+
+class GTKDoc(object):
+
+ """Class that controls a gtkdoc run.
+
+ Each instance of this class represents one gtkdoc configuration
+ and set of documentation. The gtkdoc package is a series of tools
+ run consecutively which converts inline C/C++ documentation into
+ docbook files and then into HTML. This class is suitable for
+ generating documentation or simply verifying correctness.
+
+ Keyword arguments:
+ output_dir -- The path where gtkdoc output should be placed. Generation
+ may overwrite file in this directory. Required.
+ module_name -- The name of the documentation module. For libraries this
+ is typically the library name. Required if not library path
+ is given.
+ source_dirs -- A list of paths to the source code to be scanned. Required.
+ ignored_files -- A list of filenames to ignore in the source directory. It is
+ only necessary to provide the basenames of these files.
+ Typically it is important to provide an updated list of
+ ignored files to prevent warnings about undocumented symbols.
+ decorator -- If a decorator is used to unhide certain symbols in header
+ files this parameter is required for successful scanning.
+ (default '')
+ deprecation_guard -- gtkdoc tries to ensure that symbols marked as deprecated
+ are encased in this C preprocessor define. This is required
+ to avoid gtkdoc warnings. (default '')
+ cflags -- This parameter specifies any preprocessor flags necessary for
+ building the scanner binary during gtkdoc-scanobj. Typically
+ this includes all absolute include paths necessary to resolve
+ all header dependencies. (default '')
+ ldflags -- This parameter specifies any linker flags necessary for
+ building the scanner binary during gtkdoc-scanobj. Typically
+ this includes "-lyourlibraryname". (default '')
+ library_path -- This parameter specifies the path to the directory where you
+ library resides used for building the scanner binary during
+ gtkdoc-scanobj. (default '')
+
+ doc_dir -- The path to other documentation files necessary to build
+ the documentation. This files in this directory as well as
+ the files in the 'html' subdirectory will be copied
+ recursively into the output directory. (default '')
+ main_sgml_file -- The path or name (if a doc_dir is given) of the SGML file
+ that is the considered the main page of your documentation.
+ (default: <module_name>-docs.sgml)
+ version -- The version number of the module. If this is provided,
+ a version.xml file containing the version will be created
+ in the output directory during documentation generation.
+
+ interactive -- Whether or not errors or warnings should prompt the user
+ to continue or not. When this value is false, generation
+ will continue despite warnings. (default False)
+ """
+
+ def __init__(self, **args):
+
+ # Parameters specific to scanning.
+ self.module_name = ''
+ self.source_dirs = []
+ self.ignored_files = []
+ self.decorator = ''
+ self.deprecation_guard = ''
+
+ # Parameters specific to gtkdoc-scanobj.
+ self.cflags = ''
+ self.ldflags = ''
+ self.library_path = ''
+
+ # Parameters specific to generation.
+ self.output_dir = ''
+ self.doc_dir = ''
+ self.main_sgml_file = ''
+
+ self.interactive = False
+
+ self.logger = logging.getLogger('gtkdoc')
+
+ for key, value in args.iteritems():
+ setattr(self, key, value)
+
+ def raise_error_if_not_specified(key):
+ if not getattr(self, key):
+ raise Exception('%s not specified.' % key)
+
+ raise_error_if_not_specified('output_dir')
+ raise_error_if_not_specified('source_dirs')
+ raise_error_if_not_specified('module_name')
+
+ # Make all paths absolute in case we were passed relative paths, since
+ # we change the current working directory when executing subcommands.
+ self.output_dir = os.path.abspath(self.output_dir)
+ self.source_dirs = [os.path.abspath(x) for x in self.source_dirs]
+ if self.library_path:
+ self.library_path = os.path.abspath(self.library_path)
+
+ if not self.main_sgml_file:
+ self.main_sgml_file = self.module_name + "-docs.sgml"
+
+ def generate(self, html=True):
+ self.saw_warnings = False
+
+ self._copy_doc_files_to_output_dir(html)
+ self._write_version_xml()
+ self._run_gtkdoc_scan()
+ self._run_gtkdoc_scangobj()
+ self._run_gtkdoc_mktmpl()
+ self._run_gtkdoc_mkdb()
+
+ if not html:
+ return
+
+ self._run_gtkdoc_mkhtml()
+ self._run_gtkdoc_fixxref()
+
+ def _delete_file_if_exists(self, path):
+ if not os.access(path, os.F_OK | os.R_OK):
+ return
+ self.logger.debug('deleting %s', path)
+ os.unlink(path)
+
+ def _create_directory_if_nonexistent(self, path):
+ try:
+ os.makedirs(path)
+ except OSError as error:
+ if error.errno != errno.EEXIST:
+ raise
+
+ def _raise_exception_if_file_inaccessible(self, path):
+ if not os.path.exists(path) or not os.access(path, os.R_OK):
+ raise Exception("Could not access file at: %s" % path)
+
+ def _output_has_warnings(self, outputs):
+ for output in outputs:
+ if output and output.find('warning'):
+ return True
+ return False
+
+ def _ask_yes_or_no_question(self, question):
+ if not self.interactive:
+ return True
+
+ question += ' [y/N] '
+ answer = None
+ while answer != 'y' and answer != 'n' and answer != '':
+ answer = raw_input(question).lower()
+ return answer == 'y'
+
+ def _run_command(self, args, env=None, cwd=None, print_output=True):
+ self.logger.info("Running %s", args[0])
+ self.logger.debug("Full command args: %s", str(args))
+
+ process = subprocess.Popen(args, env=env, cwd=cwd,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ stdout, stderr = process.communicate()
+
+ if print_output:
+ if stdout:
+ sys.stdout.write(stdout)
+ if stderr:
+ sys.stderr.write(stderr)
+
+ if process.returncode != 0:
+ raise Exception('%s produced a non-zero return code %i'
+ % (args[0], process.returncode))
+
+ if 'warning' in stderr or 'warning' in stdout:
+ self.saw_warnings = True
+ if not self._ask_yes_or_no_question('%s produced warnings, '
+ 'try to continue?' % args[0]):
+ raise Exception('%s step failed' % args[0])
+
+ return stdout.strip()
+
+ def _copy_doc_files_to_output_dir(self, html=True):
+ if not self.doc_dir:
+ self.logger.info('Not copying any files from doc directory,'
+ ' because no doc directory given.')
+ return
+
+ def copy_file_replacing_existing(src, dest):
+ if os.path.isdir(src):
+ self.logger.debug('skipped directory %s', src)
+ return
+ if not os.access(src, os.F_OK | os.R_OK):
+ self.logger.debug('skipped unreadable %s', src)
+ return
+
+ self._delete_file_if_exists(dest)
+
+ self.logger.debug('created %s', dest)
+ os.link(src, dest)
+
+ def copy_all_files_in_directory(src, dest):
+ for path in os.listdir(src):
+ copy_file_replacing_existing(os.path.join(src, path),
+ os.path.join(dest, path))
+
+ self.logger.info('Copying template files to output directory...')
+ self._create_directory_if_nonexistent(self.output_dir)
+ copy_all_files_in_directory(self.doc_dir, self.output_dir)
+
+ if not html:
+ return
+
+ self.logger.info('Copying HTML files to output directory...')
+ html_src_dir = os.path.join(self.doc_dir, 'html')
+ html_dest_dir = os.path.join(self.output_dir, 'html')
+ self._create_directory_if_nonexistent(html_dest_dir)
+
+ if os.path.exists(html_src_dir):
+ copy_all_files_in_directory(html_src_dir, html_dest_dir)
+
+ def _write_version_xml(self):
+ if not self.version:
+ self.logger.info('No version specified, so not writing version.xml')
+ return
+
+ version_xml_path = os.path.join(self.output_dir, 'version.xml')
+ src_version_xml_path = os.path.join(self.doc_dir, 'version.xml')
+
+ # Don't overwrite version.xml if it was in the doc directory.
+ if os.path.exists(version_xml_path) and \
+ os.path.exists(src_version_xml_path):
+ return
+
+ output_file = open(version_xml_path, 'w')
+ output_file.write(self.version)
+ output_file.close()
+
+ def _run_gtkdoc_scan(self):
+ args = ['gtkdoc-scan',
+ '--module=%s' % self.module_name,
+ '--rebuild-types']
+
+ # Each source directory should be have its own "--source-dir=" prefix.
+ args.extend(['--source-dir=%s' % path for path in self.source_dirs])
+
+ if self.decorator:
+ args.append('--ignore-decorators=%s' % self.decorator)
+ if self.deprecation_guard:
+ args.append('--deprecated-guards=%s' % self.deprecation_guard)
+ if self.output_dir:
+ args.append('--output-dir=%s' % self.output_dir)
+
+ # gtkdoc-scan wants the basenames of ignored headers, so strip the
+ # dirname. Different from "--source-dir", the headers should be
+ # specified as one long string.
+ if self.ignored_files:
+ ignored_files_basenames = \
+ [os.path.basename(x) for x in self.ignored_files]
+ args.append('--ignore-headers=%s' % ' '.join(ignored_files_basenames))
+
+ self._run_command(args)
+
+ def _run_gtkdoc_scangobj(self):
+ env = os.environ
+ ldflags = self.ldflags
+ if self.library_path:
+ ldflags = ' "-L%s" ' % self.library_path + ldflags
+ env['RUN'] = 'LD_LIBRARY_PATH="%s" ' % self.library_path
+ if ldflags:
+ env['LDFLAGS'] = ldflags
+ if self.cflags:
+ env['CFLAGS'] = self.cflags
+
+ if 'CFLAGS' in env:
+ self.logger.debug('CFLAGS=%s', env['CFLAGS'])
+ if 'LDFLAGS' in env:
+ self.logger.debug('LDFLAGS %s', env['LDFLAGS'])
+ if 'RUN' in env:
+ self.logger.debug('RUN=%s', env['RUN'])
+ self._run_command(['gtkdoc-scangobj', '--module=%s' % self.module_name],
+ env=env, cwd=self.output_dir)
+
+ def _run_gtkdoc_mktmpl(self):
+ args = ['gtkdoc-mktmpl', '--module=%s' % self.module_name]
+ self._run_command(args, cwd=self.output_dir)
+
+ def _run_gtkdoc_mkdb(self):
+ sgml_file = os.path.join(self.output_dir, self.main_sgml_file)
+ self._raise_exception_if_file_inaccessible(sgml_file)
+
+ args = ['gtkdoc-mkdb',
+ '--module=%s' % self.module_name,
+ '--main-sgml-file=%s' % sgml_file,
+ '--source-suffixes=h,c,cpp,cc',
+ '--output-format=xml',
+ '--sgml-mode']
+
+ # Each directory should be have its own "--source-dir=" prefix.
+ args.extend(['--source-dir=%s' % path for path in self.source_dirs])
+ self._run_command(args, cwd=self.output_dir)
+
+ def _run_gtkdoc_mkhtml(self):
+ html_dest_dir = os.path.join(self.output_dir, 'html')
+ if not os.path.isdir(html_dest_dir):
+ raise Exception("%s is not a directory, could not generate HTML"
+ % html_dest_dir)
+ elif not os.access(html_dest_dir, os.X_OK | os.R_OK | os.W_OK):
+ raise Exception("Could not access %s to generate HTML"
+ % html_dest_dir)
+
+ # gtkdoc-mkhtml expects the SGML path to be absolute.
+ sgml_file = os.path.join(os.path.abspath(self.output_dir),
+ self.main_sgml_file)
+ self._raise_exception_if_file_inaccessible(sgml_file)
+
+ self._run_command(['gtkdoc-mkhtml', self.module_name, sgml_file],
+ cwd=html_dest_dir)
+
+ def _run_gtkdoc_fixxref(self):
+ self._run_command(['gtkdoc-fixxref',
+ '--module-dir=html',
+ '--html-dir=html'],
+ cwd=self.output_dir)
+
+
+class PkgConfigGTKDoc(GTKDoc):
+
+ """Class reads a library's pkgconfig file to guess gtkdoc parameters.
+
+ Some gtkdoc parameters can be guessed by reading a library's pkgconfig
+ file, including the cflags, ldflags and version parameters. If you
+ provide these parameters as well, they will be appended to the ones
+ guessed via the pkgconfig file.
+
+ Keyword arguments:
+ pkg_config_path -- Path to the pkgconfig file for the library. Required.
+ """
+
+ def __init__(self, pkg_config_path, **args):
+ super(PkgConfigGTKDoc, self).__init__(**args)
+
+ if not os.path.exists(pkg_config_path):
+ raise Exception('Could not find pkg-config file at: %s'
+ % pkg_config_path)
+
+ self.cflags += " " + self._run_command(['pkg-config',
+ pkg_config_path,
+ '--cflags'], print_output=False)
+ self.ldflags += " " + self._run_command(['pkg-config',
+ pkg_config_path,
+ '--libs'], print_output=False)
+ self.version = self._run_command(['pkg-config',
+ pkg_config_path,
+ '--modversion'], print_output=False)
Property changes on: trunk/Source/WebKit2/UIProcess/API/gtk/docs/gtkdoc.py
___________________________________________________________________