scripts: include function versions in API definition

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

  <function name='virNodeNumOfDevices' file='libvirt-nodedev'
            module='libvirt-nodedev'>

we now have

  <function name='virNodeNumOfDevices' file='libvirt-nodedev'
            module='libvirt-nodedev' version='0.5.0'>

This will benefit this proposal:

  https://gitlab.com/libvirt/libvirt-go-module/-/merge_requests/7

Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
Tested-by: Victor Toso <victortoso@redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
This commit is contained in:
Daniel P. Berrangé 2021-09-23 11:40:01 +01:00
parent 4a6d874946
commit e0e0bf6628

View File

@ -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,7 +2316,15 @@ 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,
if id.type == "function":
ver = self.versions[name]
if ver is None:
raise Exception("Missing version for '%s'" % name)
output.write(" <function name='%s' file='%s' module='%s' version='%s'>\n" % (
name, self.modulename_file(id.header),
self.modulename_file(id.module), self.versions[name]))
else:
output.write(" <functype name='%s' file='%s' module='%s'>\n" % (
name, self.modulename_file(id.header),
self.modulename_file(id.module)))
#
@ -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