def normalise_signature(sig):
'''normalise a signature from gdb'''
sig = sig.strip()
- sig = re.sub('^\$[0-9]+\s=\s\{*', '', sig)
- sig = re.sub('\}(\s0x[0-9a-f]+\s<\w+>)?$', '', sig)
+ sig = re.sub('^\$[0-9]+\s=\s\{(.+)\}$', r'\1', sig)
+ sig = re.sub('^\$[0-9]+\s=\s\{(.+)\}(\s0x[0-9a-f]+\s<\w+>)+$', r'\1', sig)
+ sig = re.sub('^\$[0-9]+\s=\s(0x[0-9a-f]+)\s?(<\w+>)?$', r'\1', sig)
sig = re.sub('0x[0-9a-f]+', '0xXXXX', sig)
sig = re.sub('", <incomplete sequence (\\\\[a-z0-9]+)>', r'\1"', sig)
sa = s.split(':')
if abi_match:
matched = False
+ negative = False
for p in abi_match:
if p[0] == '!' and fnmatch.fnmatch(sa[0], p[1:]):
+ negative = True
break
elif fnmatch.fnmatch(sa[0], p):
matched = True
break
- if not matched:
+ if (not matched) and negative:
continue
Logs.debug("%s -> %s" % (sa[1], normalise_signature(sa[1])))
ret[sa[0]] = normalise_signature(sa[1])
got_error = True
if got_error:
- raise Utils.WafError('ABI for %s has changed - please fix library version then build with --abi-update\nSee http://wiki.samba.org/index.php/Waf#ABI_Checking for more information' % libname)
+ raise Utils.WafError('ABI for %s has changed - please fix library version then build with --abi-update\nSee http://wiki.samba.org/index.php/Waf#ABI_Checking for more information\nIf you have not changed any ABI, and your platform always gives this error, please configure with --abi-check-disable to skip this check' % libname)
t = Task.task_type_from_func('abi_check', abi_check_task, color='BLUE', ext_in='.bin')
topsrc = self.bld.srcnode.abspath()
abi_gen = os.path.join(topsrc, 'buildtools/scripts/abi_gen.sh')
- abi_file = "%s/%s-%s.sigs" % (self.abi_directory, self.name, self.vnum)
+ abi_file = "%s/%s-%s.sigs" % (self.abi_directory, self.version_libname,
+ self.vnum)
tsk = self.create_task('abi_check', self.link_task.outputs[0])
tsk.ABI_FILE = abi_file
def abi_process_file(fname, version, symmap):
'''process one ABI file, adding new symbols to the symmap'''
- f = open(fname, mode='r')
- for line in f:
+ for line in Utils.readf(fname).splitlines():
symname = line.split(":")[0]
if not symname in symmap:
symmap[symname] = version
- f.close()
-def abi_write_vscript(vscript, libname, current_version, versions, symmap, abi_match):
- '''write a vscript file for a library in --version-script format
-
- :param vscript: Path to the vscript file
+
+def abi_write_vscript(f, libname, current_version, versions, symmap, abi_match):
+ """Write a vscript file for a library in --version-script format.
+
+ :param f: File-like object to write to
:param libname: Name of the library, uppercased
:param current_version: Current version
:param versions: Versions to consider
:param symmap: Dictionary mapping symbols -> version
- :param abi_match: List of symbols considered to be public in the current version
- '''
+ :param abi_match: List of symbols considered to be public in the current
+ version
+ """
invmap = {}
for s in symmap:
invmap.setdefault(symmap[s], []).append(s)
- f = open(vscript, mode='w')
last_key = ""
versions = sorted(versions, key=version_key)
for k in versions:
if symver == current_version:
break
f.write("%s {\n" % symver)
- if k in invmap:
- f.write("\tglobal: \n")
+ if k in sorted(invmap.keys()):
+ f.write("\tglobal:\n")
for s in invmap.get(k, []):
f.write("\t\t%s;\n" % s);
f.write("}%s;\n\n" % last_key)
last_key = " %s" % symver
f.write("%s {\n" % current_version)
+ local_abi = filter(lambda x: x[0] == '!', abi_match)
+ global_abi = filter(lambda x: x[0] != '!', abi_match)
f.write("\tglobal:\n")
- for x in abi_match:
- f.write("\t\t%s;\n" % x)
+ if len(global_abi) > 0:
+ for x in global_abi:
+ f.write("\t\t%s;\n" % x)
+ else:
+ f.write("\t\t*;\n")
if abi_match != ["*"]:
- f.write("\tlocal: *;\n")
+ f.write("\tlocal:\n")
+ for x in local_abi:
+ f.write("\t\t%s;\n" % x[1:])
+ if len(global_abi) > 0:
+ f.write("\t\t*;\n")
f.write("};\n")
- f.close()
def abi_build_vscript(task):
version = basename[len(task.env.LIBNAME)+1:-len(".sigs")]
versions.append(version)
abi_process_file(fname, version, symmap)
- abi_write_vscript(tgt, task.env.LIBNAME, task.env.VERSION, versions, symmap,
- task.env.ABI_MATCH)
+ f = open(tgt, mode='w')
+ try:
+ abi_write_vscript(f, task.env.LIBNAME, task.env.VERSION, versions,
+ symmap, task.env.ABI_MATCH)
+ finally:
+ f.close()
def ABI_VSCRIPT(bld, libname, abi_directory, version, vscript, abi_match=None):
'''generate a vscript file for our public libraries'''
if abi_directory:
- source = bld.path.ant_glob('%s/%s-[0-9]*.sigs' % (abi_directory, libname))
+ source = bld.path.ant_glob('%s/%s-[0-9]*.sigs' % (abi_directory, libname), flat=True)
def abi_file_key(path):
return version_key(path[:-len(".sigs")].rsplit("-")[-1])
source = sorted(source.split(), key=abi_file_key)