aboutsummaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
authorMarkus Armbruster <armbru@redhat.com>2018-02-26 13:48:58 -0600
committerEric Blake <eblake@redhat.com>2018-03-02 13:14:09 -0600
commitfb0bc835e56b894cbc7236294921e5393c786ad8 (patch)
treec96c6626054c20084fc9fe268fab187c0bed20bf /scripts
parent26df4e7fab06422b21e11d039c64243ca4003147 (diff)
downloadqemu-fb0bc835e56b894cbc7236294921e5393c786ad8.zip
qemu-fb0bc835e56b894cbc7236294921e5393c786ad8.tar.gz
qemu-fb0bc835e56b894cbc7236294921e5393c786ad8.tar.bz2
qapi-gen: New common driver for code and doc generators
Whenever qapi-schema.json changes, we run six programs eleven times to update eleven files. Similar for qga/qapi-schema.json. This is silly. Replace the six programs by a single program that spits out all eleven files. The programs become modules in new Python package qapi, along with the helper library. This requires moving them to scripts/qapi/. While moving them, consistently drop executable mode bits. Signed-off-by: Markus Armbruster <armbru@redhat.com> Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com> Message-Id: <20180211093607.27351-9-armbru@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com> Reviewed-by: Michael Roth <mdroth@linux.vnet.ibm.com> [eblake: move change to one-line 'blurb' earlier in series, mention mode bit change as intentional, update qapi-code-gen.txt to match actual generated events.c file] Signed-off-by: Eric Blake <eblake@redhat.com>
Diffstat (limited to 'scripts')
-rwxr-xr-xscripts/qapi-gen.py41
-rw-r--r--scripts/qapi/__init__.py0
-rw-r--r--scripts/qapi/commands.py (renamed from scripts/qapi-commands.py)19
-rw-r--r--scripts/qapi/common.py (renamed from scripts/qapi.py)18
-rw-r--r--[-rwxr-xr-x]scripts/qapi/doc.py (renamed from scripts/qapi2texi.py)29
-rw-r--r--scripts/qapi/events.py (renamed from scripts/qapi-event.py)19
-rw-r--r--scripts/qapi/introspect.py (renamed from scripts/qapi-introspect.py)28
-rw-r--r--scripts/qapi/types.py (renamed from scripts/qapi-types.py)30
-rw-r--r--scripts/qapi/visit.py (renamed from scripts/qapi-visit.py)30
9 files changed, 73 insertions, 141 deletions
diff --git a/scripts/qapi-gen.py b/scripts/qapi-gen.py
new file mode 100755
index 0000000..2100ca1
--- /dev/null
+++ b/scripts/qapi-gen.py
@@ -0,0 +1,41 @@
+#!/usr/bin/env python
+# QAPI generator
+#
+# This work is licensed under the terms of the GNU GPL, version 2 or later.
+# See the COPYING file in the top-level directory.
+
+import sys
+from qapi.common import parse_command_line, QAPISchema
+from qapi.types import gen_types
+from qapi.visit import gen_visit
+from qapi.commands import gen_commands
+from qapi.events import gen_events
+from qapi.introspect import gen_introspect
+from qapi.doc import gen_doc
+
+
+def main(argv):
+ (input_file, output_dir, prefix, opts) = \
+ parse_command_line('bu', ['builtins', 'unmask-non-abi-names'])
+
+ opt_builtins = False
+ opt_unmask = False
+
+ for o, a in opts:
+ if o in ('-b', '--builtins'):
+ opt_builtins = True
+ if o in ('-u', '--unmask-non-abi-names'):
+ opt_unmask = True
+
+ schema = QAPISchema(input_file)
+
+ gen_types(schema, output_dir, prefix, opt_builtins)
+ gen_visit(schema, output_dir, prefix, opt_builtins)
+ gen_commands(schema, output_dir, prefix)
+ gen_events(schema, output_dir, prefix)
+ gen_introspect(schema, output_dir, prefix, opt_unmask)
+ gen_doc(schema, output_dir, prefix)
+
+
+if __name__ == '__main__':
+ main(sys.argv)
diff --git a/scripts/qapi/__init__.py b/scripts/qapi/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/scripts/qapi/__init__.py
diff --git a/scripts/qapi-commands.py b/scripts/qapi/commands.py
index c20b220..a744611 100644
--- a/scripts/qapi-commands.py
+++ b/scripts/qapi/commands.py
@@ -13,7 +13,7 @@ This work is licensed under the terms of the GNU GPL, version 2.
See the COPYING file in the top-level directory.
"""
-from qapi import *
+from qapi.common import *
def gen_command_decl(name, arg_type, boxed, ret_type):
@@ -255,11 +255,8 @@ class QAPISchemaGenCommandVisitor(QAPISchemaVisitor):
self._regy += gen_register_command(name, success_response)
-def main(argv):
- (input_file, output_dir, do_c, do_h, prefix, opts) = parse_command_line()
-
+def gen_commands(schema, output_dir, prefix):
blurb = ' * Schema-defined QAPI/QMP commands'
-
genc = QAPIGenC(blurb, __doc__)
genh = QAPIGenH(blurb, __doc__)
@@ -288,17 +285,9 @@ void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds);
''',
prefix=prefix, c_prefix=c_name(prefix, protect=False)))
- schema = QAPISchema(input_file)
vis = QAPISchemaGenCommandVisitor(prefix)
schema.visit(vis)
genc.add(vis.defn)
genh.add(vis.decl)
-
- if do_c:
- genc.write(output_dir, prefix + 'qmp-marshal.c')
- if do_h:
- genh.write(output_dir, prefix + 'qmp-commands.h')
-
-
-if __name__ == '__main__':
- main(sys.argv)
+ genc.write(output_dir, prefix + 'qmp-marshal.c')
+ genh.write(output_dir, prefix + 'qmp-commands.h')
diff --git a/scripts/qapi.py b/scripts/qapi/common.py
index f12cddd..3bc31a0 100644
--- a/scripts/qapi.py
+++ b/scripts/qapi/common.py
@@ -1932,17 +1932,15 @@ def parse_command_line(extra_options='', extra_long_options=[]):
try:
opts, args = getopt.gnu_getopt(sys.argv[1:],
- 'chp:o:' + extra_options,
- ['source', 'header', 'prefix=',
- 'output-dir='] + extra_long_options)
+ 'p:o:' + extra_options,
+ ['prefix=', 'output-dir=']
+ + extra_long_options)
except getopt.GetoptError as err:
print("%s: %s" % (sys.argv[0], str(err)), file=sys.stderr)
sys.exit(1)
output_dir = ''
prefix = ''
- do_c = False
- do_h = False
extra_opts = []
for oa in opts:
@@ -1956,23 +1954,15 @@ def parse_command_line(extra_options='', extra_long_options=[]):
prefix = a
elif o in ('-o', '--output-dir'):
output_dir = a + '/'
- elif o in ('-c', '--source'):
- do_c = True
- elif o in ('-h', '--header'):
- do_h = True
else:
extra_opts.append(oa)
- if not do_c and not do_h:
- do_c = True
- do_h = True
-
if len(args) != 1:
print("%s: need exactly one argument" % sys.argv[0], file=sys.stderr)
sys.exit(1)
fname = args[0]
- return (fname, output_dir, do_c, do_h, prefix, extra_opts)
+ return (fname, output_dir, prefix, extra_opts)
#
diff --git a/scripts/qapi2texi.py b/scripts/qapi/doc.py
index 8a604d8..cc4d5a4 100755..100644
--- a/scripts/qapi2texi.py
+++ b/scripts/qapi/doc.py
@@ -4,11 +4,10 @@
# This work is licensed under the terms of the GNU LGPL, version 2+.
# See the COPYING file in the top-level directory.
"""This script produces the documentation of a qapi schema in texinfo format"""
+
from __future__ import print_function
import re
-import sys
-
-import qapi
+import qapi.common
MSG_FMT = """
@deftypefn {type} {{}} {name}
@@ -197,7 +196,7 @@ def texi_entity(doc, what, base=None, variants=None,
+ texi_sections(doc))
-class QAPISchemaGenDocVisitor(qapi.QAPISchemaVisitor):
+class QAPISchemaGenDocVisitor(qapi.common.QAPISchemaVisitor):
def __init__(self):
self.out = None
self.cur_doc = None
@@ -272,20 +271,8 @@ def texi_schema(schema):
return gen.out
-def main(argv):
- """Takes schema argument, prints result to stdout"""
- if len(argv) != 2:
- print("%s: need exactly 1 argument: SCHEMA" % argv[0], file=sys.stderr)
- sys.exit(1)
-
- schema = qapi.QAPISchema(argv[1])
- if not qapi.doc_required:
- print("%s: need pragma 'doc-required' "
- "to generate documentation" % argv[0], file=sys.stderr)
- sys.exit(1)
- print('@c AUTOMATICALLY GENERATED, DO NOT MODIFY\n')
- print(texi_schema(schema), end='')
-
-
-if __name__ == '__main__':
- main(sys.argv)
+def gen_doc(schema, output_dir, prefix):
+ if qapi.common.doc_required:
+ gen = qapi.common.QAPIGenDoc()
+ gen.add(texi_schema(schema))
+ gen.write(output_dir, prefix + 'qapi-doc.texi')
diff --git a/scripts/qapi-event.py b/scripts/qapi/events.py
index 1f8bf62..b7dc820 100644
--- a/scripts/qapi-event.py
+++ b/scripts/qapi/events.py
@@ -12,7 +12,7 @@ This work is licensed under the terms of the GNU GPL, version 2.
See the COPYING file in the top-level directory.
"""
-from qapi import *
+from qapi.common import *
def build_event_send_proto(name, arg_type, boxed):
@@ -171,11 +171,8 @@ class QAPISchemaGenEventVisitor(QAPISchemaVisitor):
self._event_names.append(name)
-def main(argv):
- (input_file, output_dir, do_c, do_h, prefix, dummy) = parse_command_line()
-
+def gen_events(schema, output_dir, prefix):
blurb = ' * Schema-defined QAPI/QMP events'
-
genc = QAPIGenC(blurb, __doc__)
genh = QAPIGenH(blurb, __doc__)
@@ -199,17 +196,9 @@ def main(argv):
''',
prefix=prefix))
- schema = QAPISchema(input_file)
vis = QAPISchemaGenEventVisitor(prefix)
schema.visit(vis)
genc.add(vis.defn)
genh.add(vis.decl)
-
- if do_c:
- genc.write(output_dir, prefix + 'qapi-event.c')
- if do_h:
- genh.write(output_dir, prefix + 'qapi-event.h')
-
-
-if __name__ == '__main__':
- main(sys.argv)
+ genc.write(output_dir, prefix + 'qapi-event.c')
+ genh.write(output_dir, prefix + 'qapi-event.h')
diff --git a/scripts/qapi-introspect.py b/scripts/qapi/introspect.py
index cac219b..1e4f065 100644
--- a/scripts/qapi-introspect.py
+++ b/scripts/qapi/introspect.py
@@ -10,7 +10,7 @@ This work is licensed under the terms of the GNU GPL, version 2.
See the COPYING file in the top-level directory.
"""
-from qapi import *
+from qapi.common import *
# Caveman's json.dumps() replacement (we're stuck at Python 2.4)
@@ -168,20 +168,8 @@ const char %(c_name)s[] = %(c_string)s;
self._gen_json(name, 'event', {'arg-type': self._use_type(arg_type)})
-def main(argv):
- # Debugging aid: unmask QAPI schema's type names
- # We normally mask them, because they're not QMP wire ABI
- opt_unmask = False
-
- (input_file, output_dir, do_c, do_h, prefix, opts) = \
- parse_command_line('u', ['unmask-non-abi-names'])
-
- for o, a in opts:
- if o in ('-u', '--unmask-non-abi-names'):
- opt_unmask = True
-
+def gen_introspect(schema, output_dir, prefix, opt_unmask):
blurb = ' * QAPI/QMP schema introspection'
-
genc = QAPIGenC(blurb, __doc__)
genh = QAPIGenH(blurb, __doc__)
@@ -192,17 +180,9 @@ def main(argv):
''',
prefix=prefix))
- schema = QAPISchema(input_file)
vis = QAPISchemaGenIntrospectVisitor(prefix, opt_unmask)
schema.visit(vis)
genc.add(vis.defn)
genh.add(vis.decl)
-
- if do_c:
- genc.write(output_dir, prefix + 'qmp-introspect.c')
- if do_h:
- genh.write(output_dir, prefix + 'qmp-introspect.h')
-
-
-if __name__ == '__main__':
- main(sys.argv)
+ genc.write(output_dir, prefix + 'qmp-introspect.c')
+ genh.write(output_dir, prefix + 'qmp-introspect.h')
diff --git a/scripts/qapi-types.py b/scripts/qapi/types.py
index 7d23544..aa3c01e 100644
--- a/scripts/qapi-types.py
+++ b/scripts/qapi/types.py
@@ -13,7 +13,7 @@ This work is licensed under the terms of the GNU GPL, version 2.
# See the COPYING file in the top-level directory.
"""
-from qapi import *
+from qapi.common import *
# variants must be emitted before their container; track what has already
@@ -241,22 +241,8 @@ class QAPISchemaGenTypeVisitor(QAPISchemaVisitor):
self._gen_type_cleanup(name)
-def main(argv):
- # If you link code generated from multiple schemata, you want only one
- # instance of the code for built-in types. Generate it only when
- # opt_builtins, enabled by command line option -b. See also
- # QAPISchemaGenTypeVisitor.visit_end().
- opt_builtins = False
-
- (input_file, output_dir, do_c, do_h, prefix, opts) = \
- parse_command_line('b', ['builtins'])
-
- for o, a in opts:
- if o in ('-b', '--builtins'):
- opt_builtins = True
-
+def gen_types(schema, output_dir, prefix, opt_builtins):
blurb = ' * Schema-defined QAPI types'
-
genc = QAPIGenC(blurb, __doc__)
genh = QAPIGenH(blurb, __doc__)
@@ -272,17 +258,9 @@ def main(argv):
#include "qapi/util.h"
'''))
- schema = QAPISchema(input_file)
vis = QAPISchemaGenTypeVisitor(opt_builtins)
schema.visit(vis)
genc.add(vis.defn)
genh.add(vis.decl)
-
- if do_c:
- genc.write(output_dir, prefix + 'qapi-types.c')
- if do_h:
- genh.write(output_dir, prefix + 'qapi-types.h')
-
-
-if __name__ == '__main__':
- main(sys.argv)
+ genc.write(output_dir, prefix + 'qapi-types.c')
+ genh.write(output_dir, prefix + 'qapi-types.h')
diff --git a/scripts/qapi-visit.py b/scripts/qapi/visit.py
index 3c23a93..3ed7816 100644
--- a/scripts/qapi-visit.py
+++ b/scripts/qapi/visit.py
@@ -13,7 +13,7 @@ This work is licensed under the terms of the GNU GPL, version 2.
See the COPYING file in the top-level directory.
"""
-from qapi import *
+from qapi.common import *
def gen_visit_decl(name, scalar=False):
@@ -324,22 +324,8 @@ class QAPISchemaGenVisitVisitor(QAPISchemaVisitor):
self.defn += gen_visit_alternate(name, variants)
-def main(argv):
- # If you link code generated from multiple schemata, you want only one
- # instance of the code for built-in types. Generate it only when
- # opt_builtins, enabled by command line option -b. See also
- # QAPISchemaGenVisitVisitor.visit_end().
- opt_builtins = False
-
- (input_file, output_dir, do_c, do_h, prefix, opts) = \
- parse_command_line('b', ['builtins'])
-
- for o, a in opts:
- if o in ('-b', '--builtins'):
- opt_builtins = True
-
+def gen_visit(schema, output_dir, prefix, opt_builtins):
blurb = ' * Schema-defined QAPI visitors'
-
genc = QAPIGenC(blurb, __doc__)
genh = QAPIGenH(blurb, __doc__)
@@ -359,17 +345,9 @@ def main(argv):
''',
prefix=prefix))
- schema = QAPISchema(input_file)
vis = QAPISchemaGenVisitVisitor(opt_builtins)
schema.visit(vis)
genc.add(vis.defn)
genh.add(vis.decl)
-
- if do_c:
- genc.write(output_dir, prefix + 'qapi-visit.c')
- if do_h:
- genh.write(output_dir, prefix + 'qapi-visit.h')
-
-
-if __name__ == '__main__':
- main(sys.argv)
+ genc.write(output_dir, prefix + 'qapi-visit.c')
+ genh.write(output_dir, prefix + 'qapi-visit.h')