Albert Astals Cid <[email protected]> writes:

> El dimecres, 6 de setembre de 2017, a les 8:32:03 CEST, Carlos Garcia Campos 
> va escriure:
>> Albert Astals Cid <[email protected]> writes:
>> > So gtkdoc upstream seems to have cmake support, so I *almost* made it work
>> > 
>> > But it's obviously failing to pick up some stuff since the generated files
>> > look wrong.
>> > 
>> > See
>> > http://i.imgur.com/gdSH1pI.png
>> > vs
>> > http://i.imgur.com/5QSy6oP.png
>> > 
>> > Patch attached.
>> > 
>> > Can anyone try to have a look? Or anyone knows who could i ask for help on
>> > the glib/gnome side? I've sank a few hours into this and not sure i can
>> > move it forward without further help.
>> 
>> I'll look at it (probably during the weekend)
>
> Any luck?

Yes, I tried to use the CMake files provided by gtk-doc but it didn't
really work, so in the end it was a lot easier to reuse the WebKit
approach. In WebKit we have a gtkdoc.py that is a standalone generic
module to deal with gtk-doc and another script called from CMake that
uses that module to generate the docs. In the patch attached I've added
the gtkdoc.py, just copied from WebKit, and a custom script to use it in
poppler. It also updates the CMake files to build, install and include
documentation in the tarball. It works fine here, please try it out and
let me know whether it works for you too.

> Is this something we could decouple from the build? (i.e. in the same way we 
> have Doxygen for the cpp/qt4/qt5 frontends but you don't need cmake support)
>
> Cheers,
>   Albert
>
>> 
>> > Cheers,
>> > 
>> >   Albert
>> > 
>> > diff --git a/CMakeLists.txt b/CMakeLists.txt
>> > index f557bdaf..4a012db4 100644
>> > --- a/CMakeLists.txt
>> > +++ b/CMakeLists.txt
>> > @@ -161,7 +161,10 @@ if(CAIRO_FOUND)
>> > 
>> >    set(POPPLER_GLIB_DISABLE_SINGLE_INCLUDES "")
>> >    if(ENABLE_GLIB)
>> >    
>> >      macro_optional_find_package(GLIB)
>> > 
>> > -    if(NOT GLIB_FOUND)
>> > +    if(GLIB_FOUND)
>> > +      find_package(GtkDoc 1.25 QUIET)
>> > +      MESSAGE("GtkDoc_FOUND ${GtkDoc_FOUND}")
>> > +    else()
>> > 
>> >        set(ENABLE_GLIB OFF)
>> >      
>> >      endif()
>> >    
>> >    endif()
>> > 
>> > @@ -786,7 +789,7 @@ show_end_message_yesno("qt5 wrapper" ENABLE_QT5)
>> > 
>> >  show_end_message_yesno("glib wrapper" ENABLE_GLIB)
>> >  show_end_message_yesno("  introspection" INTROSPECTION_FOUND)
>> >  show_end_message_yesno("cpp wrapper" ENABLE_CPP)
>> > 
>> > -show_end_message("use gtk-doc" "not supported with this CMake build
>> > system") +show_end_message_yesno("use gtk-doc" GtkDoc_FOUND)
>> > 
>> >  show_end_message_yesno("use libjpeg" ENABLE_LIBJPEG)
>> >  show_end_message_yesno("use libpng" ENABLE_LIBPNG)
>> >  show_end_message_yesno("use libtiff" ENABLE_LIBTIFF)
>> > 
>> > diff --git a/glib/CMakeLists.txt b/glib/CMakeLists.txt
>> > index 26724ec1..455c9d49 100644
>> > --- a/glib/CMakeLists.txt
>> > +++ b/glib/CMakeLists.txt
>> > @@ -84,7 +84,7 @@ add_library(poppler-glib SHARED ${poppler_glib_SRCS}
>> > ${poppler_glib_generated_SR> 
>> >  set_target_properties(poppler-glib PROPERTIES VERSION 8.9.0 SOVERSION 8)
>> >  target_link_libraries(poppler-glib poppler ${GLIB2_LIBRARIES}
>> >  ${CAIRO_LIBRARIES} ${FREETYPE_LIBRARIES}) if(HAVE_PTHREAD)
>> > 
>> > -   target_link_libraries(poppler-glib -lpthread)
>> > +   target_link_libraries(poppler-glib pthread)
>> > 
>> >  endif()
>> >  install(TARGETS poppler-glib RUNTIME DESTINATION bin LIBRARY DESTINATION
>> >  lib${LIB_SUFFIX} ARCHIVE DESTINATION lib${LIB_SUFFIX})> 
>> > @@ -134,3 +134,7 @@ if (HAVE_INTROSPECTION)
>> > 
>> >    gir_add_introspections(INTROSPECTION_GIRS)
>> >  
>> >  endif ()
>> > 
>> > +
>> > +if (GtkDoc_FOUND)
>> > +  add_subdirectory(reference)
>> > +endif()
>> > diff --git a/glib/reference/CMakeLists.txt b/glib/reference/CMakeLists.txt
>> > new file mode 100644
>> > index 00000000..c22557fd
>> > --- /dev/null
>> > +++ b/glib/reference/CMakeLists.txt
>> > @@ -0,0 +1,26 @@
>> > +SET(exec_prefix "/usr/")
>> > +
>> > +find_package(GtkDoc 1.25 REQUIRED)
>> > +
>> > +# For some reason poppler has a -lpthread that I don't know exactly where
>> > it comes from +# but the GtkDoc cmake code chokes on it, so replace to
>> > pthread only +get_target_property(target_link_flags poppler
>> > LINK_LIBRARIES)
>> > +string(REPLACE "-lpthread" "pthread" fixed_target_link_flags
>> > "${target_link_flags}") +set_target_properties(poppler PROPERTIES
>> > LINK_LIBRARIES "${fixed_target_link_flags}") +
>> > +# Create the doc-poppler target.
>> > +gtk_doc_add_module(
>> > +    poppler
>> > +    SOURCE ${CMAKE_SOURCE_DIR}/glib/
>> > +    ${CMAKE_SOURCE_DIR}/glib/reference/
>> > +    LIBRARIES poppler-glib poppler
>> > +)
>> > +
>> > +# Build doc-poppler as part of the default target. Without this, you
>> > would
>> > +# have to explicitly run something like `make doc-poppler` to build the
>> > docs. +add_custom_target(documentation ALL DEPENDS doc-poppler)
>> > +
>> > +# # Install the docs. (This assumes you're using the GNUInstallDirs CMake
>> > module +# # to set the CMAKE_INSTALL_DOCDIR variable correctly).
>> > +# install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/poppler/html
>> > +#         DESTINATION ${CMAKE_INSTALL_DOCDIR})
>> > _______________________________________________
>> > poppler mailing list
>> > [email protected]
>> > https://lists.freedesktop.org/mailman/listinfo/poppler
>
>

Attachment: signature.asc
Description: PGP signature

>From ed0f69aab8d9d25a0e4e0e93696730e490cae3e8 Mon Sep 17 00:00:00 2001
From: Carlos Garcia Campos <[email protected]>
Date: Wed, 20 Sep 2017 19:38:14 +0200
Subject: [PATCH] Add gtk-doc support to CMake build

---
 CMakeLists.txt                |   4 +-
 glib/CMakeLists.txt           |   7 +-
 glib/reference/CMakeLists.txt |  12 ++
 gtkdoc.py                     | 440 ++++++++++++++++++++++++++++++++++++++++++
 make-glib-api-docs            |  66 +++++++
 5 files changed, 525 insertions(+), 4 deletions(-)
 create mode 100644 glib/reference/CMakeLists.txt
 create mode 100644 gtkdoc.py
 create mode 100755 make-glib-api-docs

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4288be38..c38a1f28 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -39,6 +39,7 @@ option(ENABLE_SPLASH "Build the Splash graphics backend." ON)
 option(ENABLE_UTILS "Compile poppler command line utils." ON)
 option(ENABLE_CPP "Compile poppler cpp wrapper." ON)
 option(ENABLE_GLIB "Compile poppler glib wrapper." ON)
+option(ENABLE_GTK_DOC "Whether to generate glib API documentation." OFF)
 option(ENABLE_QT4 "Compile poppler qt4 wrapper." ON)
 option(ENABLE_QT5 "Compile poppler qt5 wrapper." ON)
 set(ENABLE_LIBOPENJPEG "auto" CACHE STRING "Use libopenjpeg for JPX streams. Possible values: auto, openjpeg1, openjpeg2, unmaintained, none. 'auto' prefers openjpeg2 over openjpeg1 if both are available. 'unmaintained' gives you the internal unmaintained decoder. Use at your own risk. 'none' compiles no JPX decoder at all. Default: auto")
@@ -779,8 +780,8 @@ show_end_message_yesno("qt4 wrapper" ENABLE_QT4)
 show_end_message_yesno("qt5 wrapper" ENABLE_QT5)
 show_end_message_yesno("glib wrapper" ENABLE_GLIB)
 show_end_message_yesno("  introspection" INTROSPECTION_FOUND)
+show_end_message_yesno("  gtk-doc" ENABLE_GTK_DOC)
 show_end_message_yesno("cpp wrapper" ENABLE_CPP)
-show_end_message("use gtk-doc" "not supported with this CMake build system")
 show_end_message_yesno("use libjpeg" ENABLE_LIBJPEG)
 show_end_message_yesno("use libpng" ENABLE_LIBPNG)
 show_end_message_yesno("use libtiff" ENABLE_LIBTIFF)
@@ -839,5 +840,6 @@ add_custom_target(dist
         COMMAND git log --stat | fmt --split-only > ${CMAKE_BINARY_DIR}/ChangeLog
         COMMAND git archive --prefix=${ARCHIVE_NAME}/ HEAD > ${CMAKE_BINARY_DIR}/${ARCHIVE_NAME}.tar
         COMMAND tar -C ${CMAKE_BINARY_DIR} -rf ${CMAKE_BINARY_DIR}/${ARCHIVE_NAME}.tar ChangeLog --transform='s,,${ARCHIVE_NAME}/,'
+        COMMAND tar -C ${CMAKE_BINARY_DIR} -rf ${CMAKE_BINARY_DIR}/${ARCHIVE_NAME}.tar glib/reference/html --transform='s,,${ARCHIVE_NAME}/,'
         COMMAND xz -9 ${CMAKE_BINARY_DIR}/${ARCHIVE_NAME}.tar
     WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
diff --git a/glib/CMakeLists.txt b/glib/CMakeLists.txt
index 26724ec1..ab73f6ed 100644
--- a/glib/CMakeLists.txt
+++ b/glib/CMakeLists.txt
@@ -83,9 +83,6 @@ set(poppler_glib_generated_SRCS
 add_library(poppler-glib SHARED ${poppler_glib_SRCS} ${poppler_glib_generated_SRCS})
 set_target_properties(poppler-glib PROPERTIES VERSION 8.9.0 SOVERSION 8)
 target_link_libraries(poppler-glib poppler ${GLIB2_LIBRARIES} ${CAIRO_LIBRARIES} ${FREETYPE_LIBRARIES})
-if(HAVE_PTHREAD)
-   target_link_libraries(poppler-glib -lpthread)
-endif()
 install(TARGETS poppler-glib RUNTIME DESTINATION bin LIBRARY DESTINATION lib${LIB_SUFFIX} ARCHIVE DESTINATION lib${LIB_SUFFIX})
 
 install(FILES
@@ -134,3 +131,7 @@ if (HAVE_INTROSPECTION)
 
   gir_add_introspections(INTROSPECTION_GIRS)
 endif ()
+
+if(ENABLE_GTK_DOC)
+  add_subdirectory(reference)
+endif()
diff --git a/glib/reference/CMakeLists.txt b/glib/reference/CMakeLists.txt
new file mode 100644
index 00000000..2743ffbc
--- /dev/null
+++ b/glib/reference/CMakeLists.txt
@@ -0,0 +1,12 @@
+add_custom_command(
+  OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/glib-docs-build.stamp
+  DEPENDS poppler-glib
+  COMMAND ${CMAKE_SOURCE_DIR}/make-glib-api-docs --src-dir=${CMAKE_SOURCE_DIR} --build-dir=${CMAKE_BINARY_DIR}
+  COMMAND touch ${CMAKE_CURRENT_BINARY_DIR}/glib-docs-build.stamp
+)
+
+add_custom_target(glib-docs ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/glib-docs-build.stamp)
+
+install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html/
+  DESTINATION "${SHARE_INSTALL_DIR}/gtk-doc/html/poppler"
+)
diff --git a/gtkdoc.py b/gtkdoc.py
new file mode 100644
index 00000000..48f862a3
--- /dev/null
+++ b/gtkdoc.py
@@ -0,0 +1,440 @@
+# 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 directories of source code to be scanned.
+                          Required if headers is not specified.
+    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.
+    headers            -- A list of paths to headers to be scanned. Required if source_dirs
+                          is not specified.
+    namespace          -- The library namespace.
+    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)
+
+    virtual_root       -- A temporary installation directory which is used as the root
+                          where the actual installation prefix lives; this is mostly
+                          useful for packagers, and should be set to what is given to
+                          make install as DESTDIR.
+    """
+
+    def __init__(self, args):
+
+        # Parameters specific to scanning.
+        self.module_name = ''
+        self.source_dirs = []
+        self.headers = []
+        self.ignored_files = []
+        self.namespace = ''
+        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 = ''
+
+        # Parameters specific to gtkdoc-fixxref.
+        self.cross_reference_deps = []
+
+        self.interactive = False
+
+        self.logger = logging.getLogger('gtkdoc')
+
+        for key, value in iter(args.items()):
+            setattr(self, key, value)
+
+        if not getattr(self, 'output_dir'):
+            raise Exception('output_dir not specified.')
+        if not getattr(self, 'module_name'):
+            raise Exception('module_name not specified.')
+        if not getattr(self, 'source_dirs') and not getattr(self, 'headers'):
+            raise Exception('Neither source_dirs nor headers specified.' % key)
+
+        # 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]
+        self.headers = [os.path.abspath(x) for x in self.headers]
+        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_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, ignore_warnings=False):
+        if print_output:
+            self.logger.debug("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 = [b.decode("utf-8") for b in process.communicate()]
+
+        if print_output:
+            if stdout:
+                try:
+                    sys.stdout.write(stdout.encode("utf-8"))
+                except UnicodeDecodeError:
+                    sys.stdout.write(stdout)
+            if stderr:
+                try:
+                    sys.stderr.write(stderr.encode("utf-8"))
+                except UnicodeDecodeError:
+                    sys.stderr.write(stderr)
+
+        if process.returncode != 0:
+            raise Exception('%s produced a non-zero return code %i'
+                             % (args[0], process.returncode))
+
+        if not ignore_warnings and ('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)
+            try:
+                os.link(src, dest)
+            except OSError:
+                os.symlink(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.debug('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.debug('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 _ignored_files_basenames(self):
+        return ' '.join([os.path.basename(x) for x in self.ignored_files])
+
+    def _run_gtkdoc_scan(self):
+        args = ['gtkdoc-scan',
+                '--module=%s' % self.module_name,
+                '--rebuild-types']
+
+        if not self.headers:
+            # 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)
+
+        # We only need to pass the list of ignored files if the we are not using an explicit list of headers.
+        if not self.headers:
+            # 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.
+            ignored_files_basenames = self._ignored_files_basenames()
+            if ignored_files_basenames:
+                args.append('--ignore-headers=%s' % ignored_files_basenames)
+
+        if self.headers:
+            args.extend(self.headers)
+
+        self._run_command(args)
+
+    def _run_gtkdoc_scangobj(self):
+        env = os.environ
+        ldflags = self.ldflags
+        if self.library_path:
+            additional_ldflags = ''
+            for arg in env.get('LDFLAGS', '').split(' '):
+                if arg.startswith('-L'):
+                    additional_ldflags = '%s %s' % (additional_ldflags, arg)
+            ldflags = ' "-L%s" %s ' % (self.library_path, additional_ldflags) + ldflags
+            current_ld_library_path = env.get('LD_LIBRARY_PATH')
+            if current_ld_library_path:
+                env['RUN'] = 'LD_LIBRARY_PATH="%s:%s" ' % (self.library_path, current_ld_library_path)
+            else:
+                env['RUN'] = 'LD_LIBRARY_PATH="%s" ' % self.library_path
+
+        if ldflags:
+            env['LDFLAGS'] = '%s %s' % (ldflags, env.get('LDFLAGS', ''))
+        if self.cflags:
+            env['CFLAGS'] = '%s %s' % (self.cflags, env.get('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_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']
+
+        if self.namespace:
+            args.append('--name-space=%s' % self.namespace)
+
+        ignored_files_basenames = self._ignored_files_basenames()
+        if ignored_files_basenames:
+            args.append('--ignore-files=%s' % ignored_files_basenames)
+
+        # 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):
+        args = ['gtkdoc-fixxref',
+                '--module=%s' % self.module_name,
+                '--module-dir=html',
+                '--html-dir=html']
+        args.extend(['--extra-dir=%s' % extra_dir for extra_dir in self.cross_reference_deps])
+        self._run_command(args, cwd=self.output_dir, ignore_warnings=True)
+
+    def rebase_installed_docs(self):
+        if not os.path.isdir(self.output_dir):
+            raise Exception("Tried to rebase documentation before generating it.")
+        html_dir = os.path.join(self.virtual_root + self.prefix, 'share', 'gtk-doc', 'html', self.module_name)
+        if not os.path.isdir(html_dir):
+            return
+        args = ['gtkdoc-rebase',
+                '--relative',
+                '--html-dir=%s' % html_dir]
+        args.extend(['--other-dir=%s' % extra_dir for extra_dir in self.cross_reference_deps])
+        if self.virtual_root:
+            args.extend(['--dest-dir=%s' % self.virtual_root])
+        self._run_command(args, cwd=self.output_dir)
+
+    def api_missing_documentation(self):
+        unused_doc_file = os.path.join(self.output_dir, self.module_name + "-unused.txt")
+        if not os.path.exists(unused_doc_file) or not os.access(unused_doc_file, os.R_OK):
+            return []
+        return open(unused_doc_file).read().splitlines()
+
+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)
+
+        pkg_config = os.environ.get('PKG_CONFIG', 'pkg-config')
+
+        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)
+        self.prefix = self._run_command([pkg_config,
+                                         pkg_config_path,
+                                         '--variable=prefix'], print_output=False)
diff --git a/make-glib-api-docs b/make-glib-api-docs
new file mode 100755
index 00000000..6fbe4494
--- /dev/null
+++ b/make-glib-api-docs
@@ -0,0 +1,66 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2017 Carlos Garcia Campos <[email protected]>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+import argparse
+import logging
+import os
+from gtkdoc import PkgConfigGTKDoc
+
+def configure_logging(verbose):
+    level = logging.DEBUG if verbose 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'))
+
+
+parser = argparse.ArgumentParser(description='Make poppler GLib API documentation.')
+parser.add_argument('-v', '--verbose', action='store_true', default = False,
+                    help='Whether or not to run in verbose mode.')
+parser.add_argument('--skip-html', action='store_true',
+                    help='Whether or not to skip HTML generation, which can be slow.')
+parser.add_argument('-s', '--src-dir', action='store', default='.', dest='src_dir',
+                    help='The source directory')
+parser.add_argument('-b', '--build-dir', action='store', default='build', dest='build_dir',
+                    help='The build directory')
+args = parser.parse_args()
+configure_logging(args.verbose)
+
+pkgconfig_file = os.path.join(args.build_dir, 'poppler-glib.pc')
+pkgconfig_path = os.environ.get("PKG_CONFIG_PATH")
+os.environ['PKG_CONFIG_PATH'] = args.build_dir
+if pkgconfig_path:
+    os.environ['PKG_CONFIG_PATH'] += ':' + pkgconfig_path
+
+gtkdoc = PkgConfigGTKDoc(pkgconfig_file, {
+    'library_path': os.path.join(args.build_dir, 'glib'),
+    'module_name': 'poppler',
+    'doc_dir': os.path.join(args.src_dir, 'glib', 'reference'),
+    'output_dir': os.path.join(args.build_dir, 'glib', 'reference'),
+    'main_sgml_file': 'poppler-docs.sgml',
+    'source_dirs': [os.path.join(args.src_dir, 'glib')],
+    'cflags': '-I%s' % os.path.join(args.src_dir, 'glib'),
+    'ignored_files': ['poppler-private.h', 'poppler-input-stream.h', 'poppler-cached-file-loader.h', 'demo']
+})
+
+gtkdoc.generate(not args.skip_html)
-- 
2.14.1

-- 
Carlos Garcia Campos
PGP key: http://pgp.mit.edu:11371/pks/lookup?op=get&search=0x523E6462
_______________________________________________
poppler mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/poppler

Reply via email to