qapi: pluggable backend code generators

The 'qapi.backend.QAPIBackend' class defines an API contract for code
generators. The current generator is put into a new class
'qapi.backend.QAPICBackend' and made to be the default impl.

A custom generator can be requested using the '-k' arg which takes a
fully qualified python class name

   qapi-gen.py -B the.python.module.QAPIMyBackend

This allows out of tree code to use the QAPI generator infrastructure
to create new language bindings for QAPI schemas. This has the caveat
that the QAPI generator APIs are not guaranteed stable, so consumers
of this feature may have to update their code to be compatible with
future QEMU releases.

Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
Message-ID: <20250224182030.2089959-1-berrange@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
[Error checking and messages tweaked]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
This commit is contained in:
Daniel P. Berrangé 2025-02-24 18:20:30 +00:00 committed by Markus Armbruster
parent 5e4c466e6a
commit dde279925c
2 changed files with 108 additions and 35 deletions

63
scripts/qapi/backend.py Normal file
View file

@ -0,0 +1,63 @@
# This work is licensed under the terms of the GNU GPL, version 2 or later.
# See the COPYING file in the top-level directory.
from abc import ABC, abstractmethod
from .commands import gen_commands
from .events import gen_events
from .features import gen_features
from .introspect import gen_introspect
from .schema import QAPISchema
from .types import gen_types
from .visit import gen_visit
class QAPIBackend(ABC):
@abstractmethod
def generate(self,
schema: QAPISchema,
output_dir: str,
prefix: str,
unmask: bool,
builtins: bool,
gen_tracing: bool) -> None:
"""
Generate code for the given schema into the target directory.
:param schema: The primary QAPI schema object.
:param output_dir: The output directory to store generated code.
:param prefix: Optional C-code prefix for symbol names.
:param unmask: Expose non-ABI names through introspection?
:param builtins: Generate code for built-in types?
:raise QAPIError: On failures.
"""
class QAPICBackend(QAPIBackend):
def generate(self,
schema: QAPISchema,
output_dir: str,
prefix: str,
unmask: bool,
builtins: bool,
gen_tracing: bool) -> None:
"""
Generate C code for the given schema into the target directory.
:param schema_file: The primary QAPI schema file.
:param output_dir: The output directory to store generated code.
:param prefix: Optional C-code prefix for symbol names.
:param unmask: Expose non-ABI names through introspection?
:param builtins: Generate code for built-in types?
:raise QAPIError: On failures.
"""
gen_types(schema, output_dir, prefix, builtins)
gen_features(schema, output_dir, prefix)
gen_visit(schema, output_dir, prefix, builtins)
gen_commands(schema, output_dir, prefix, gen_tracing)
gen_events(schema, output_dir, prefix)
gen_introspect(schema, output_dir, prefix, unmask)