[v4,4/5] meson: Run Doxygen on the Meson build

Submitted by Daniel Stone on Aug. 28, 2018, 10:19 p.m.

Details

Message ID 20180828221919.18208-4-daniels@collabora.com
State New
Series "Series without cover letter"
Headers show

Commit Message

Daniel Stone Aug. 28, 2018, 10:19 p.m.
From: Emmanuele Bassi <ebassi@gnome.org>

Add a script which generates the desired Doxygen configuration for our
various output formats and executes it using that configuration.

[daniels: Properly install into mandir/man3 via some gross
          paramaterisation, generate real stamp files.]

Reviewed-by: Daniel Stone <daniels@collabora.com>
---
 doc/doxygen/.gitignore      |   1 +
 doc/doxygen/gen-doxygen.py  | 105 ++++++++++++++++++++++++++++++++
 doc/doxygen/meson.build     | 115 ++++++++++++++++++++++++++++++++++++
 doc/doxygen/xml/meson.build |  18 ++++++
 doc/meson.build             |   6 +-
 5 files changed, 240 insertions(+), 5 deletions(-)
 create mode 100755 doc/doxygen/gen-doxygen.py
 create mode 100644 doc/doxygen/meson.build
 create mode 100644 doc/doxygen/xml/meson.build

Patch hide | download patch | download mbox

diff --git a/doc/doxygen/.gitignore b/doc/doxygen/.gitignore
index a85e6c0d..5c544d6c 100644
--- a/doc/doxygen/.gitignore
+++ b/doc/doxygen/.gitignore
@@ -2,3 +2,4 @@  doxygen_sqlite3.db
 html/
 wayland.doxygen
 xml/
+!xml/meson.build
diff --git a/doc/doxygen/gen-doxygen.py b/doc/doxygen/gen-doxygen.py
new file mode 100755
index 00000000..1bb07e57
--- /dev/null
+++ b/doc/doxygen/gen-doxygen.py
@@ -0,0 +1,105 @@ 
+#!/usr/bin/env python3
+
+import argparse
+import datetime
+import errno
+import os
+import subprocess
+import sys
+
+# Custom configuration for each documentation format
+doxygen_templates = {
+    'xml': [
+        'GENERATE_XML=YES\n',
+        'XML_OUTPUT={format}/{section}\n',
+        'INPUT= {files}\n',
+    ],
+    'html': [
+        'GENERATE_HTML=YES\n',
+        'HTML_OUTPUT={format}/{section}\n',
+        'PROJECT_NAME=\"Wayland {section} API\"\n',
+        'INPUT= {files}\n',
+    ],
+    'man': [
+        'GENERATE_MAN=YES\n',
+        'MAN_OUTPUT={format}\n',
+        'MAN_SUBDIR=.\n',
+        'JAVADOC_AUTOBRIEF=NO\n',
+        'INPUT= {files}\n',
+    ],
+}
+
+def load_doxygen_file(doxyfile):
+    with open(doxyfile, 'r') as f:
+        res = f.readlines()
+    return res
+
+def get_template(outformat):
+    for (k,v) in doxygen_templates.items():
+        if outformat.startswith(k):
+            return v
+
+def gen_doxygen_file(data, outformat, section, files):
+    for l in get_template(outformat):
+        data.append(l.format(format=outformat, section=section, files=' '.join(files)))
+    return data
+
+parser = argparse.ArgumentParser(description='Generate docs with Doxygen')
+parser.add_argument('doxygen_file',
+                    help='The doxygen file to use')
+parser.add_argument('files',
+                    help='The list of files to parse',
+                    metavar='FILES',
+                    nargs='+')
+parser.add_argument('--builddir',
+                    help='The build directory',
+                    metavar='DIR',
+                    default='.')
+parser.add_argument('--section',
+                    help='The section to build',
+                    metavar='NAME',
+                    default='Client')
+parser.add_argument('--output-format',
+                    help='The output format: xml, html, man',
+                    metavar='FORMAT',
+                    default='xml')
+parser.add_argument('--stamp',
+                    help='Stamp file to output',
+                    metavar='STAMP_FILE',
+                    nargs='?',
+                    type=argparse.FileType('w'))
+
+args = parser.parse_args()
+
+# Merge the doxyfile with our custom templates
+conf = load_doxygen_file(args.doxygen_file)
+conf = gen_doxygen_file(conf, args.output_format, args.section, args.files)
+
+# Doxygen is not clever enough to create the directories it
+# needs beforehand
+try:
+    os.makedirs(os.path.join(args.builddir, args.output_format))
+except OSError as e:
+    if e.errno != errno.EEXIST:
+        raise e
+
+# Run Doxygen with the generated doxyfile
+cmd = subprocess.Popen(['doxygen', '-'], stdin=subprocess.PIPE)
+cmd.stdin.write(''.join(conf).encode('utf-8'))
+cmd.stdin.close()
+if cmd.wait() != 0:
+    sys.exit(1)
+
+# This is a bit of a hack; Doxygen will generate way more files than we
+# want to install, but there's no way to know how many at configuration
+# time. Since we want to install only the wl_* man pages anyway, we can
+# delete the other files and let Meson install the whole man3 subdirectory
+if args.output_format.startswith('man'):
+    manpath = os.path.join(args.builddir, args.output_format)
+    for filename in os.listdir(manpath):
+        full_path = os.path.join(manpath, filename)
+        if not filename.startswith('wl_'):
+            os.remove(full_path)
+
+if args.stamp:
+   args.stamp.write(str(datetime.datetime.now()))
diff --git a/doc/doxygen/meson.build b/doc/doxygen/meson.build
new file mode 100644
index 00000000..68523631
--- /dev/null
+++ b/doc/doxygen/meson.build
@@ -0,0 +1,115 @@ 
+# Here be dragons
+doxygen = find_program('doxygen')
+
+dot = find_program('dot')
+dot_gv = [
+  [ 'wayland-architecture', files('dot/wayland-architecture.gv') ],
+  [ 'x-architecture', files('dot/x-architecture.gv') ],
+]
+
+# This is a workaround for Meson's custom_target() directive, which
+# currently does not support outputs pointing to a sub-directory
+dot_png = []
+dot_map = []
+subdir('xml')
+
+doxygen = configuration_data()
+doxygen.set('VERSION', meson.project_version())
+doxygen.set('top_builddir', meson.build_root())
+wayland_doxygen = configure_file(
+  input: 'wayland.doxygen.in',
+  output: 'wayland.doxygen',
+  configuration: doxygen,
+)
+
+shared_files = files([
+  '../../src/wayland-util.h',
+])
+
+client_files = files([
+  '../../src/wayland-client.c',
+  '../../src/wayland-client.h',
+  '../../src/wayland-client-core.h',
+])
+
+server_files = files([
+  '../../src/event-loop.c',
+  '../../src/wayland-server.c',
+  '../../src/wayland-server.h',
+  '../../src/wayland-server-core.h',
+  '../../src/wayland-shm.c',
+])
+
+extra_client_files = [
+  'mainpage.dox',
+  wayland_client_protocol_h,
+]
+
+extra_server_files = [
+  'mainpage.dox',
+  wayland_server_protocol_h,
+]
+
+# formats = [ format_name, [ [ section_name, files ] ] ]
+formats = [
+  [
+    'xml', [
+      [ 'Client', shared_files + client_files, ],
+      [ 'Server', shared_files + server_files, ],
+    ]
+  ],
+  [
+    'html', [
+      [ 'Client', shared_files + client_files + extra_client_files, ],
+      [ 'Server', shared_files + server_files + extra_server_files, ],
+    ]
+  ],
+]
+
+gen_doxygen = find_program('gen-doxygen.py')
+foreach f: formats
+  f_name = f[0]
+  sections = f[1]
+
+  foreach s: sections
+    s_name = s[0]
+    s_files = s[1]
+    t_name = '@0@-@1@-doc'.format(f_name, s_name)
+
+    # We do not really need an output file, but Meson
+    # will complain if one is not set, so we use a
+    # dummy 'stamp' file
+    custom_target(t_name,
+      command: [
+        gen_doxygen,
+        '--builddir=@OUTDIR@',
+        '--section=@0@'.format(s_name),
+        '--output-format=@0@'.format(f_name),
+	'--stamp=doc/doxygen/@0@.stamp'.format(t_name),
+        wayland_doxygen,
+        '@INPUT@',
+      ],
+      input: s_files,
+      output: '@0@.stamp'.format(t_name),
+      depends: [dot_png, dot_map],
+      build_by_default: true,
+    )
+  endforeach
+endforeach
+
+man_files = shared_files + client_files + server_files
+custom_target('man-pages-3',
+  command: [
+    gen_doxygen,
+    '--builddir=@OUTDIR@',
+    '--output-format=man3',
+    '--stamp=doc/doxygen/man3.stamp',
+    wayland_doxygen,
+    '@INPUT@',
+  ],
+  input: man_files,
+  output: 'man3',
+  build_by_default: true,
+  install: true,
+  install_dir: join_paths(get_option('prefix'), get_option('mandir')),
+)
diff --git a/doc/doxygen/xml/meson.build b/doc/doxygen/xml/meson.build
new file mode 100644
index 00000000..58826c51
--- /dev/null
+++ b/doc/doxygen/xml/meson.build
@@ -0,0 +1,18 @@ 
+# dot_png: list of PNG targets
+# dot_map: list of MAP targets
+foreach gv: dot_gv
+  name = gv[0]
+  infile = gv[1]
+
+  dot_png += custom_target(name + '.png',
+    command: [ dot, '-Tpng', '-o@OUTPUT@', '@INPUT@' ],
+    input: infile,
+    output: name + '.png',
+  )
+
+  dot_map += custom_target(name + '.map',
+    command: [ dot, '-Tcmapx_np', '-o@OUTPUT@', '@INPUT@' ],
+    input: infile,
+    output: name + '.map',
+  )
+endforeach
diff --git a/doc/meson.build b/doc/meson.build
index 8c743fe9..f05c57b3 100644
--- a/doc/meson.build
+++ b/doc/meson.build
@@ -1,5 +1 @@ 
-xsltproc = find_program('xsltproc', required: false)
-doxygen = find_program('doxygen')
-xmlto = find_program('xmlto')
-dot = find_program('dot')
-
+subdir('doxygen')

Comments

Pekka Paalanen Aug. 30, 2018, 2:31 p.m.
On Tue, 28 Aug 2018 23:19:18 +0100
Daniel Stone <daniels@collabora.com> wrote:

> From: Emmanuele Bassi <ebassi@gnome.org>
> 
> Add a script which generates the desired Doxygen configuration for our
> various output formats and executes it using that configuration.
> 
> [daniels: Properly install into mandir/man3 via some gross
>           paramaterisation, generate real stamp files.]
> 
> Reviewed-by: Daniel Stone <daniels@collabora.com>
> ---
>  doc/doxygen/.gitignore      |   1 +
>  doc/doxygen/gen-doxygen.py  | 105 ++++++++++++++++++++++++++++++++
>  doc/doxygen/meson.build     | 115 ++++++++++++++++++++++++++++++++++++
>  doc/doxygen/xml/meson.build |  18 ++++++
>  doc/meson.build             |   6 +-
>  5 files changed, 240 insertions(+), 5 deletions(-)
>  create mode 100755 doc/doxygen/gen-doxygen.py
>  create mode 100644 doc/doxygen/meson.build
>  create mode 100644 doc/doxygen/xml/meson.build

Hi,

I read through this whole ordeal, and there is only one thing I can
complain about: it doesn't actually install the docs. I mean the
$prefix/share/doc directory where at the end of the dungeon should be
the HTML docs.

The contortions to get this even building are so nasty that the end
result is impressively clean. I'm ok with all the code here so far.
Once the docs get installed, I could diff the installed files.

Mind, autotools builddir=srcdir 'make distclean' will wipe
doc/doxygen/xml/meson.build.


Thanks,
pq