[v3,3/4] meson: Run Doxygen on the Meson build

Submitted by Daniel Stone on July 21, 2018, 3:31 p.m.

Details

Message ID 20180721153124.17946-4-daniels@collabora.com
State New
Series "Meson build"
Headers show

Commit Message

Daniel Stone July 21, 2018, 3:31 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.

This is currently broken as clean fails:
	ninja: error: remove(doc/doxygen/man): Directory not empty
	Cleaning... 92 files.

[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..d5ec6dc0
--- /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',
+  get_variable('wayland_client_protocol_h'),
+]
+
+extra_server_files = [
+  'mainpage.dox',
+  get_variable('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')