From cdd31870ecfb682ff1a405e1fcef3af4e13cb733 Mon Sep 17 00:00:00 2001 From: Andres Freund Date: Wed, 21 Sep 2022 08:49:45 -0700 Subject: [PATCH v15 12/14] meson: Add xmllint/xsltproc wrapper script to handle dependencies automatically --- doc/src/sgml/meson.build | 38 ++++++++++++++------ doc/src/sgml/xmltools_dep_wrapper | 60 +++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+), 10 deletions(-) create mode 100644 doc/src/sgml/xmltools_dep_wrapper diff --git a/doc/src/sgml/meson.build b/doc/src/sgml/meson.build index ba2a261e7a4..e6781d0deae 100644 --- a/doc/src/sgml/meson.build +++ b/doc/src/sgml/meson.build @@ -2,7 +2,7 @@ docs = [] alldocs = [] doc_generated = [] -xmllint = find_program(get_option('XMLLINT'), native: true, required: false) +xmllint_bin = find_program(get_option('XMLLINT'), native: true, required: false) version_sgml = configure_file( @@ -60,14 +60,23 @@ doc_generated += custom_target('keywords-table.sgml', ) # For everything else we need at least xmllint -if not xmllint.found() +if not xmllint_bin.found() subdir_done() endif pandoc = find_program('pandoc', native: true, required: false) -xsltproc = find_program(get_option('XSLTPROC'), native: true, required: false) +xsltproc_bin = find_program(get_option('XSLTPROC'), native: true, required: false) fop = find_program('fop', native: true, required: false) +xmltools_wrapper = [ + python, files('xmltools_dep_wrapper'), + '--targetname', '@OUTPUT@', '--depfile', '@DEPFILE@' +] + +xmllint = xmltools_wrapper + [ + '--tool', xmllint_bin, '--', +] + # Run validation only once, common to all subsequent targets. While # we're at it, also resolve all entities (that is, copy all included # files into one big file). This helps tools that don't understand @@ -75,6 +84,7 @@ fop = find_program('fop', native: true, required: false) postgres_full_xml = custom_target('postgres-full.xml', input: 'postgres.sgml', output: 'postgres-full.xml', + depfile: 'postgres-full.xml.d', command: [xmllint, '--noent', '--valid', '--path', '@OUTDIR@', '-o', '@OUTPUT@', '@INPUT@'], depends: doc_generated, build_by_default: false, @@ -86,18 +96,20 @@ alldocs += postgres_full_xml # # Full documentation as html, text # -if xsltproc.found() +if xsltproc_bin.found() xsltproc_flags = [ '--stringparam', 'pg.version', pg_version, '--param', 'website.stylesheet', '1' ] + xsltproc = xmltools_wrapper + [ + '--tool', xsltproc_bin, '--', + ] - # FIXME: Should use a wrapper around xsltproc --load-trace to compute a - # depfile html = custom_target('html', input: ['stylesheet.xsl', postgres_full_xml], output: 'html', + depfile: 'html.d', depends: doc_generated, command: [xsltproc, '-o', '@OUTDIR@/', xsltproc_flags, '@INPUT@'], build_by_default: false, @@ -110,6 +122,7 @@ if xsltproc.found() html_help = custom_target('html_help', input: ['stylesheet-hh.xsl', postgres_full_xml], output: 'htmlhelp', + depfile: 'htmlhelp.d', depends: doc_generated, command: [xsltproc, '--path', '@OUTDIR@', '-o', '@OUTDIR@/', xsltproc_flags, '@INPUT@'], build_by_default: false, @@ -121,6 +134,7 @@ if xsltproc.found() postgres_html = custom_target('postgres.html', input: ['stylesheet-html-nochunk.xsl', postgres_full_xml], output: 'postgres.html', + depfile: 'postgres.html.d', depends: doc_generated, command: [xsltproc, '--path', '@OUTDIR@', '-o', '@OUTPUT@', xsltproc_flags, '@INPUT@'], build_by_default: false, @@ -144,10 +158,11 @@ endif # # INSTALL in html, text # -if xsltproc.found() +if xsltproc_bin.found() install_xml = custom_target('INSTALL.xml', input: ['standalone-profile.xsl', 'standalone-install.xml'], output: 'INSTALL.xml', + depfile: 'INSTALL.xml.d', depends: doc_generated + [postgres_full_xml], command: [xsltproc, '--path', '@OUTDIR@', '-o', '@OUTPUT@', xsltproc_flags, '--xinclude', '@INPUT@'], build_by_default: false, @@ -155,6 +170,7 @@ if xsltproc.found() install_html = custom_target('INSTALL.html', input: ['stylesheet-text.xsl', install_xml], output: 'INSTALL.html', + depfile: 'INSTALL.html.d', command: [xsltproc, '--path', '@OUTDIR@', '-o', '@OUTPUT@', xsltproc_flags, '@INPUT@'], build_by_default: false, ) @@ -177,11 +193,12 @@ endif # # Man pages # -if xsltproc.found() +if xsltproc_bin.found() # FIXME: implement / consider sqlmansectnum logic man = custom_target('man', input: ['stylesheet-man.xsl', postgres_full_xml], output: ['man1', 'man3', 'man7'], + depfile: 'man.d', depends: doc_generated, command: [xsltproc, '--path', '@OUTDIR@', '-o', '@OUTDIR@/', xsltproc_flags, '@INPUT@'], build_by_default: false, @@ -195,7 +212,7 @@ endif # # Full documentation as PDF # -if fop.found() and xsltproc.found() +if fop.found() and xsltproc_bin.found() xsltproc_fo_flags = xsltproc_flags + ['--stringparam', 'img.src.path', meson.current_source_dir() + '/'] foreach format, detail: {'A4': 'A4', 'US': 'USletter'} @@ -206,6 +223,7 @@ if fop.found() and xsltproc.found() input: ['stylesheet-fo.xsl', postgres_full_xml], output: [postgres_x_fo_f], depends: doc_generated, + depfile: postgres_x_fo_f + '.d', command: [xsltproc, '--path', '@OUTDIR@/', xsltproc_fo_flags, '--stringparam', 'paper.type', detail, '-o', '@OUTPUT@', '@INPUT@'], @@ -230,7 +248,7 @@ endif # This was previously implemented using dbtoepub - but that doesn't seem to # support running in build != source directory (i.e. VPATH builds already # weren't supported). -if pandoc.found() and xsltproc.found() +if pandoc.found() and xsltproc_bin.found() postgres_epub = custom_target('postgres.epub', input: postgres_full_xml, output: 'postgres.epub', diff --git a/doc/src/sgml/xmltools_dep_wrapper b/doc/src/sgml/xmltools_dep_wrapper new file mode 100644 index 00000000000..52b94e3fcaf --- /dev/null +++ b/doc/src/sgml/xmltools_dep_wrapper @@ -0,0 +1,60 @@ +#!/usr/bin/env python3 + +import argparse +import re +import subprocess +import sys + +parser = argparse.ArgumentParser( + description='generate dependency file for docs') + +parser.add_argument('--targetname', type=str, required=False, nargs='+') +parser.add_argument('--depfile', type=str, required=False) +parser.add_argument('--tool', type=str, required=True) + +parser.add_argument('flags', nargs='*') + +args = parser.parse_args() + +if args.depfile: + depfile_result_list = [] + + command = [args.tool, '--load-trace'] + args.flags + # --load-trace flag displays all the documents + # loaded during the processing to stderr + res = subprocess.run(command, stderr=subprocess.PIPE, + universal_newlines=True) + # if exit code is different than 0, exit + if res.returncode: + exit(res.returncode) + + # get line start from targetname + line_start = '' + for name in args.targetname: + line_start = line_start + name + ' ' + line_start = line_start.strip() + ': ' + + # collect only file paths + line_re = re.compile('^Loaded URL="([^"]+)"') + with open(args.depfile, 'w') as f: + for line in res.stderr.split('\n'): + if line == '': + continue + m = re.match(line_re, line) + + # continue to show errors + if m is None: + print(line, file=sys.stderr) + continue + + fname = m.group(1) + if fname.startswith('http:'): + continue + if fname.startswith('file://'): + fname = fname.split('file://')[1] + f.write(line_start + fname + '\n') + +else: + command = [args.tool] + args.flags + res = subprocess.run(command) + exit(res.returncode) -- 2.37.3.542.gdd3f6c4cae