Members of the KDE Community are recommended to subscribe to the kde-community mailing list at to allow them to participate in important discussions and receive other important announcements

Commit 3eb3369b authored by Sandro Knauß's avatar Sandro Knauß Committed by Ben Cooksley

check-abi: refactor script.

move abi-compatibilty.yaml into own class and move some parts into Library class.

Differential Revision:
parent c90b101d
Pipeline #1177 skipped with stage
......@@ -29,6 +29,13 @@ class Library:
self.library = library
self.candidates = []
def __getitem__(self, key):
return self.library[key]
def reportPath(self):
return "compat_reports/{cmakePackage}_compat_report.html".format(cmakePackage=self['cmakePackage'])
def addCandidate(self, key, entry):
entry['packageName'] = key
......@@ -46,13 +53,12 @@ class Library:
if released:
# get the first released version, that is available
candidate = min(released, key=lambda i: HASH2TAG[i['scmRevision']])"Found tag %s(%s) to check against.", HASH2TAG[candidate['scmRevision']].version, candidate['scmRevision'])
candidate['tag'] = HASH2TAG[candidate['scmRevision']]
#TODO: we may want to return None, as the library was never released so far.
# get oldest candidate.
candidate = min(self.candidates, key=lambda e:e['timestamp'])
logging.warning("No released version was found, just use the oldest commit.")
# the candidate needs to be older than the current build.
if timestamp < candidate['timestamp']:
......@@ -61,6 +67,39 @@ class Library:
return candidate
class ABICompatibilityResults:
"""Representing the content of abi-compatibility-results.yaml.
- First add the library via addLibrary
- Afterwards you can extent the directory via __get__
- At the end, create the fia via write
def __init__(self):
self.dict = {}
def __getitem__(self, library):
return self.dict[library]
def addLibrary(self, library):
self.dict[library] = {}
def write(self):
d = {}
for library in self.dict:
cantidate = library.candidate()
entry = {
'reportPath': library.reportPath,
'ownCommit': library['scmRevision'],
'otherCommit': candidate['scmRevision'],
if 'tag' in candidate:
entry['tag'] = candidate['tag'].version
d[library['cmakePackage']] = entry
with open('abi-compatibility-results.yaml', 'w') as f:
f.write(yaml.dump(d, default_flow_style=False))
def parseACCOutputToDict(stdout):
"""Parse output of abi-compliance-checker for further processing and returning a dict.
extract binary/source compatibility from acc
......@@ -139,6 +178,7 @@ def updateAccMetadataVersion1(entry):
entry["cmakePackage"] = entry["libname"]
entry["targets"] = {i:entry["SONAME"] for i in entry["targets"]}
# Find all libraries of current git hash.
for key, entry in ourArchive.serverManifest.items():
......@@ -158,33 +198,39 @@ if not libraries:"No libraries found.")
# Find all availabe reference dumps
# Find all available reference dumps
# * same cmakePackage
# * same SONAME otherwise we have a ABI bump and than it is safe to break ABI
# * same SONAME, otherwise we have a ABI bump and than it is safe to break ABI
for key, entry in ourArchive.serverManifest.items():
if entry['platform'] != arguments.platform:
for l in libraries:
# Ignore builds on other branches
if keepBuildGroup and entry["branchGroup"] != arguments.branchGroup:
if entry["project"] != arguments.project:
if entry["scmRevision"] == scmRevision:
for l in libraries:
cmakePackage = l.library["cmakePackage"]
targets = l.library["targets"]
soname = max(targets.values())
for key, entry in ourArchive.serverManifest.items():
if key == l.packageName:
if entry['platform'] != arguments.platform:
# We want to search for the cmakePackage
if entry["cmakePackage"] != cmakePackage:
# Ignore builds on other branches
if keepBuildGroup and entry["branchGroup"] != arguments.branchGroup:
# TODO: as we may have bundled multiple libraries in one cmakePackage,
# we properly need a smater way.
if max(entry["targets"].values()) == soname:
l.addCandidate(key, entry)
sameSONAME = False
for name, target in targets.items():
......@@ -205,7 +251,7 @@ for l in libraries:
retval = 0
# the dictonary that will be written to abi-compatibility-results.yaml
resultsYamlFile = {}
resultsYamlFile = ABICompatibilityResults()
for l in libraries:
library = l.library
......@@ -216,29 +262,24 @@ for l in libraries:"Did not found any older build for %s, nothing to check ABI against.", cmakePackage)
continue"check %s(old) -> %s(new)", candidate['scmRevision'], library['scmRevision'])
if 'tag' in candidate:"Found tag %s(%s) to check against.", candidate['tag'].version, candidate['scmRevision'])
logging.warning("No released version was found.")
# get the packages, we want to test against each other
newLibraryPath, _ = ourArchive.retrievePackage(l.packageName)
oldLibraryPath, _ = ourArchive.retrievePackage(candidate['packageName'])"check %s(old) -> %s(new)", candidate['scmRevision'], library['scmRevision'])
reportPath = "compat_reports/{cmakePackage}_compat_report.html".format(cmakePackage=cmakePackage)
# Basic result yml information
yml = {
'reportPath': reportPath,
'ownCommit': scmRevision,
'otherCommit': candidate['scmRevision'],
resultsYamlFile[cmakePackage] = yml
if candidate['scmRevision'] in HASH2TAG:
yml['tag'] = HASH2TAG[candidate['scmRevision']].version
# Add library to results yaml file
# check ABI and write compat reports
cmd = [
"-report-path", reportPath,
"-report-path", l.reportPath,
"-l", cmakePackage,
"--old", oldLibraryPath,
"--new", newLibraryPath,
......@@ -247,20 +288,19 @@ for l in libraries:
prog =, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
except subprocess.CalledProcessError as e:
if e.returncode == 1: # that means that we are not compatible, but still valid output.
logging.warning("abi-compliance-checker exited with 1:\n%s", e.stdout.decode())
if e.returncode == 1: # ABI not compatible, but still valid output.
logging.warning("%s\nabi-compliance-checker exited with 1 (not compatible)", e.stdout.decode())
logging.error("abi-compliance-checker exited with %s:\nstdout:\n\t%s\nstderr:\n\t%s", e.returncode, e.stdout.decode(), e.stderr.decode())
retval = e.returncode
yml['error'] = e.returncode
resultsYamlFile[l]['error'] = e.returncode
with open('abi-compatibility-results.yaml', 'w') as f:
f.write(yaml.dump(resultsYamlFile, default_flow_style=False))
# We had an issue with one of the ABIs
if retval != 0 and accSettings['checkABIDumpFailHard']:
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment