Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 29668e3

Browse files
committed
meson: docs: Add xml{lint,proc} wrapper to collect dependencies
meson/ninja do not support specifying dependencies via globs (as those make it significantly more expensive to check the current build state). Instead targets should emit dependency information when running that then can be cheaply re-checked during future builds. To handle xmllint and xsltproc invocations in the docs, add and use a wrapper that uses --load-trace to collect dependency information. Reviewed-by: Peter Eisentraut <peter.eisentraut@enterprisedb.com> Author: Nazir Bilal Yavuz <byavuz81@gmail.com> Author: Andres Freund <andres@anarazel.de> Discussion: https://postgr.es/m/c5736f70-bb6d-8d25-e35c-e3d886e4e905@enterprisedb.com
1 parent db0e5bf commit 29668e3

File tree

2 files changed

+84
-11
lines changed

2 files changed

+84
-11
lines changed

doc/src/sgml/meson.build

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ docs = []
22
alldocs = []
33
doc_generated = []
44

5-
xmllint = find_program(get_option('XMLLINT'), native: true, required: false)
5+
xmllint_bin = find_program(get_option('XMLLINT'), native: true, required: false)
66

77

88
version_sgml = configure_file(
@@ -60,21 +60,31 @@ doc_generated += custom_target('keywords-table.sgml',
6060
)
6161

6262
# For everything else we need at least xmllint
63-
if not xmllint.found()
63+
if not xmllint_bin.found()
6464
subdir_done()
6565
endif
6666

6767
pandoc = find_program('pandoc', native: true, required: false)
68-
xsltproc = find_program(get_option('XSLTPROC'), native: true, required: false)
68+
xsltproc_bin = find_program(get_option('XSLTPROC'), native: true, required: false)
6969
fop = find_program('fop', native: true, required: false)
7070

71+
xmltools_wrapper = [
72+
python, files('xmltools_dep_wrapper'),
73+
'--targetname', '@OUTPUT@', '--depfile', '@DEPFILE@'
74+
]
75+
76+
xmllint = xmltools_wrapper + [
77+
'--tool', xmllint_bin, '--',
78+
]
79+
7180
# Run validation only once, common to all subsequent targets. While
7281
# we're at it, also resolve all entities (that is, copy all included
7382
# files into one big file). This helps tools that don't understand
7483
# vpath builds (such as dbtoepub).
7584
postgres_full_xml = custom_target('postgres-full.xml',
7685
input: 'postgres.sgml',
7786
output: 'postgres-full.xml',
87+
depfile: 'postgres-full.xml.d',
7888
command: [xmllint, '--noent', '--valid', '--path', '@OUTDIR@', '-o', '@OUTPUT@', '@INPUT@'],
7989
depends: doc_generated,
8090
build_by_default: false,
@@ -86,18 +96,20 @@ alldocs += postgres_full_xml
8696
#
8797
# Full documentation as html, text
8898
#
89-
if xsltproc.found()
99+
if xsltproc_bin.found()
90100
xsltproc_flags = [
91101
'--stringparam', 'pg.version', pg_version,
92102
'--param', 'website.stylesheet', '1'
93103
]
94104

105+
xsltproc = xmltools_wrapper + [
106+
'--tool', xsltproc_bin, '--',
107+
]
95108

96-
# FIXME: Should use a wrapper around xsltproc --load-trace to compute a
97-
# depfile
98109
html = custom_target('html',
99110
input: ['stylesheet.xsl', postgres_full_xml],
100111
output: 'html',
112+
depfile: 'html.d',
101113
depends: doc_generated,
102114
command: [xsltproc, '-o', '@OUTDIR@/', xsltproc_flags, '@INPUT@'],
103115
build_by_default: false,
@@ -110,6 +122,7 @@ if xsltproc.found()
110122
html_help = custom_target('html_help',
111123
input: ['stylesheet-hh.xsl', postgres_full_xml],
112124
output: 'htmlhelp',
125+
depfile: 'htmlhelp.d',
113126
depends: doc_generated,
114127
command: [xsltproc, '--path', '@OUTDIR@', '-o', '@OUTDIR@/', xsltproc_flags, '@INPUT@'],
115128
build_by_default: false,
@@ -121,6 +134,7 @@ if xsltproc.found()
121134
postgres_html = custom_target('postgres.html',
122135
input: ['stylesheet-html-nochunk.xsl', postgres_full_xml],
123136
output: 'postgres.html',
137+
depfile: 'postgres.html.d',
124138
depends: doc_generated,
125139
command: [xsltproc, '--path', '@OUTDIR@', '-o', '@OUTPUT@', xsltproc_flags, '@INPUT@'],
126140
build_by_default: false,
@@ -144,17 +158,19 @@ endif
144158
#
145159
# INSTALL in html, text
146160
#
147-
if xsltproc.found()
161+
if xsltproc_bin.found()
148162
install_xml = custom_target('INSTALL.xml',
149163
input: ['standalone-profile.xsl', 'standalone-install.xml'],
150164
output: 'INSTALL.xml',
165+
depfile: 'INSTALL.xml.d',
151166
depends: doc_generated + [postgres_full_xml],
152167
command: [xsltproc, '--path', '@OUTDIR@', '-o', '@OUTPUT@', xsltproc_flags, '--xinclude', '@INPUT@'],
153168
build_by_default: false,
154169
)
155170
install_html = custom_target('INSTALL.html',
156171
input: ['stylesheet-text.xsl', install_xml],
157172
output: 'INSTALL.html',
173+
depfile: 'INSTALL.html.d',
158174
command: [xsltproc, '--path', '@OUTDIR@', '-o', '@OUTPUT@', xsltproc_flags, '@INPUT@'],
159175
build_by_default: false,
160176
)
@@ -177,11 +193,12 @@ endif
177193
#
178194
# Man pages
179195
#
180-
if xsltproc.found()
196+
if xsltproc_bin.found()
181197
# FIXME: implement / consider sqlmansectnum logic
182198
man = custom_target('man',
183199
input: ['stylesheet-man.xsl', postgres_full_xml],
184200
output: ['man1', 'man3', 'man7'],
201+
depfile: 'man.d',
185202
depends: doc_generated,
186203
command: [xsltproc, '--path', '@OUTDIR@', '-o', '@OUTDIR@/', xsltproc_flags, '@INPUT@'],
187204
build_by_default: false,
@@ -195,17 +212,19 @@ endif
195212
#
196213
# Full documentation as PDF
197214
#
198-
if fop.found() and xsltproc.found()
215+
if fop.found() and xsltproc_bin.found()
199216
xsltproc_fo_flags = xsltproc_flags + ['--stringparam', 'img.src.path', meson.current_source_dir() + '/']
200217

201218
foreach format, detail: {'A4': 'A4', 'US': 'USletter'}
202219
postgres_x_fo_f = 'postgres-@0@.fo'.format(format)
220+
postgres_x_fo_dep = 'postgres-@0@.fo.d'.format(format)
203221
postgres_x_pdf_f = 'postgres-@0@.pdf'.format(format)
204222

205223
postgres_x_fo = custom_target(postgres_x_fo_f,
206224
input: ['stylesheet-fo.xsl', postgres_full_xml],
207-
output: [postgres_x_fo_f],
225+
output: postgres_x_fo_f,
208226
depends: doc_generated,
227+
depfile: postgres_x_fo_dep,
209228
command: [xsltproc, '--path', '@OUTDIR@/', xsltproc_fo_flags,
210229
'--stringparam', 'paper.type', detail,
211230
'-o', '@OUTPUT@', '@INPUT@'],
@@ -230,7 +249,7 @@ endif
230249
# This was previously implemented using dbtoepub - but that doesn't seem to
231250
# support running in build != source directory (i.e. VPATH builds already
232251
# weren't supported).
233-
if pandoc.found() and xsltproc.found()
252+
if pandoc.found() and xsltproc_bin.found()
234253
postgres_epub = custom_target('postgres.epub',
235254
input: postgres_full_xml,
236255
output: 'postgres.epub',

doc/src/sgml/xmltools_dep_wrapper

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
#!/usr/bin/env python3
2+
3+
# A small wrapper around xmllint and xsltproc that collects dependency
4+
# information (in gcc's format) using --load-trace.
5+
6+
import argparse
7+
import re
8+
import subprocess
9+
import sys
10+
11+
parser = argparse.ArgumentParser(
12+
description='generate dependency file for docs')
13+
14+
parser.add_argument('--targetname', type=str, required=False, nargs='+')
15+
parser.add_argument('--depfile', type=str, required=False)
16+
parser.add_argument('--tool', type=str, required=True)
17+
parser.add_argument('flags', nargs='*')
18+
19+
args = parser.parse_args()
20+
21+
if args.depfile:
22+
command = [args.tool, '--load-trace'] + args.flags
23+
24+
# list of targets that depend on the loaded files we see via --load-trace
25+
line_start = ' '.join(args.targetname) + ': '
26+
27+
# --load-trace flag displays all the documents loaded during the processing
28+
# to stderr
29+
res = subprocess.run(command, stderr=subprocess.PIPE,
30+
universal_newlines=True)
31+
32+
line_re = re.compile('^Loaded URL="([^"]+)"')
33+
with open(args.depfile, 'w') as f:
34+
for line in res.stderr.splitlines():
35+
m = re.match(line_re, line)
36+
37+
# continue to show errors
38+
if m is None:
39+
print(line, file=sys.stderr)
40+
continue
41+
# Absolute paths are printed as file://, relative paths as-is. We
42+
# don't care about http://, as a) those will be printed even if
43+
# resolved locally b) we couldn't have a dependency anyway.
44+
fname = m.group(1)
45+
if fname.startswith('http://'):
46+
continue
47+
if fname.startswith('file://'):
48+
fname = fname.split('file://')[1]
49+
f.write(line_start + fname + '\n')
50+
else:
51+
command = [args.tool] + args.flags
52+
res = subprocess.run(command)
53+
54+
exit(res.returncode)

0 commit comments

Comments
 (0)