From e0e0bf662896240f2293eb60e23d2570f110fa5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= Date: Thu, 23 Sep 2021 11:40:01 +0100 Subject: [PATCH] scripts: include function versions in API definition MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In order to auto-generate more of the language binding code, it is desirable to know what libvirt version an API was introduced in. We can extract this information from the .syms files and expose it in the API description eg instead of we now have This will benefit this proposal: https://gitlab.com/libvirt/libvirt-go-module/-/merge_requests/7 Reviewed-by: Michal Privoznik Tested-by: Victor Toso Signed-off-by: Daniel P. Berrangé --- scripts/apibuild.py | 68 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 62 insertions(+), 6 deletions(-) diff --git a/scripts/apibuild.py b/scripts/apibuild.py index 9b29466e1d..bdd3077c48 100755 --- a/scripts/apibuild.py +++ b/scripts/apibuild.py @@ -2030,8 +2030,9 @@ class CParser: class docBuilder: """A documentation builder""" - def __init__(self, name, path='.', directories=['.'], includes=[]): + def __init__(self, name, syms, path='.', directories=['.'], includes=[]): self.name = name + self.syms = syms self.path = path self.directories = directories if name == "libvirt": @@ -2044,6 +2045,7 @@ class docBuilder: self.includes = includes + list(admin_included_files.keys()) self.modules = {} self.headers = {} + self.versions = {} self.idx = index() self.xref = {} self.index = {} @@ -2114,6 +2116,44 @@ class docBuilder: self.modules[module] = idx self.idx.merge_public(idx) + def scanVersions(self): + prefix = self.name.upper().replace("-", "_") + "_" + + version = None + prevversion = None + with open(self.syms, "r") as syms: + while True: + line = syms.readline() + if not line: + break + line = line.strip() + if line.startswith("#"): + continue + if line == "": + continue + + if line.startswith(prefix) and line.endswith(" {"): + version = line[len(prefix):-2] + elif line == "global:": + continue + elif line == "local:": + continue + elif line.startswith("}"): + if prevversion is None: + if line != "};": + raise Exception("Unexpected closing version") + else: + if line != ("} %s%s;" % (prefix, prevversion)): + raise Exception("Unexpected end of version '%s': %s'" % (line, "} " + prefix + version)) + + prevversion = version + version = None + elif line.endswith(";") and version is not None: + func = line[:-1] + self.versions[func] = version + else: + raise Exception("Unexpected line in syms file: %s" % line) + def scan(self): for directory in self.directories: files = glob.glob(directory + "/*.c") @@ -2136,6 +2176,7 @@ class docBuilder: self.headers[file] = None self.scanHeaders() self.scanModules() + self.scanVersions() def modulename_file(self, file): module = os.path.basename(file) @@ -2275,9 +2316,17 @@ class docBuilder: print("=>", id) # NB: this is consumed by a regex in 'getAPIFilenames' in hvsupport.pl - output.write(" <%s name='%s' file='%s' module='%s'>\n" % (id.type, - name, self.modulename_file(id.header), - self.modulename_file(id.module))) + if id.type == "function": + ver = self.versions[name] + if ver is None: + raise Exception("Missing version for '%s'" % name) + output.write(" \n" % ( + name, self.modulename_file(id.header), + self.modulename_file(id.module), self.versions[name])) + else: + output.write(" \n" % ( + name, self.modulename_file(id.header), + self.modulename_file(id.module))) # # Processing of conditionals modified by Bill 1/1/05 # @@ -2406,9 +2455,16 @@ class app: print(msg) def rebuild(self, name, srcdir, builddir): - if name not in ["libvirt", "libvirt-qemu", "libvirt-lxc", "libvirt-admin"]: + syms = { + "libvirt": srcdir + "/../src/libvirt_public.syms", + "libvirt-qemu": srcdir + "/../src/libvirt_qemu.syms", + "libvirt-lxc": srcdir + "/../src/libvirt_lxc.syms", + "libvirt-admin": srcdir + "/../src/admin/libvirt_admin_public.syms", + } + if name not in syms: self.warning("rebuild() failed, unknown module %s" % name) return None + builder = None if glob.glob(srcdir + "/../src/libvirt.c") != []: if not quiet: @@ -2418,7 +2474,7 @@ class app: srcdir + "/../src/util", srcdir + "/../include/libvirt", builddir + "/../include/libvirt"] - builder = docBuilder(name, builddir, dirs, []) + builder = docBuilder(name, syms[name], builddir, dirs, []) else: self.warning("rebuild() failed, unable to guess the module") return None