Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • pkg/apertis-dev-tools
  • fdanis/apertis-dev-tools
  • alee/apertis-dev-tools
  • pkg-rebase-trixie/apertis-dev-tools
  • sietze.vanbuuren-ext/apertis-dev-tools
5 results
Show changes
Commits on Source (4)
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Files: *
Copyright: 2012-2016, 2018, 2019, Collabora Ltd.
License: MPL-2.0
Files: tools/*
Copyright: 2019, 2022, Collabora Ltd
License: MPL-2.0
Files: tools/ade
tools/devroot-enter
tools/import-debian-package
Copyright: 2012-2016, 2018, 2019, Collabora Ltd.
License: MPL-2.0
Files: doc/* doc/man/devroot-enter.1 doc/man/devroot-enter.pod
Copyright:
2012-2016 Collabora Ltd.
License: MPL-2.0
apertis-dev-tools (0.2022.5) apertis; urgency=medium
* apertis-abi-compare:
- Add support of ARM packages via cross-compiling
-- Dylan Aïssi <dylan.aissi@collabora.com> Tue, 18 Oct 2022 10:58:44 +0200
apertis-dev-tools (0.2022.4) apertis; urgency=medium
* apertis-abi-compare:
......
......@@ -30,19 +30,21 @@ import xml.etree.ElementTree as ET
# Do an immediate flush for stdout to avoid mixed ordering of stdout and stderr output
print = functools.partial(print, flush=True)
def extract_debs(input_folder, output_folder):
list_file = list(pathlib.Path(input_folder).glob('**/*.deb'))
for file in list_file:
subprocess.run(['/usr/bin/dpkg-deb', '-x',
file, output_folder], check=True)
return list_file
def clean_build_deps(builddeps):
builddeps = re.sub("[\(\[].*?[\)\]]", "", builddeps)
builddeps = builddeps.replace(" ", "")
builddeps = builddeps.split(",")
builddeps = re.sub('[\(\[].*?[\)\]]', '', builddeps)
builddeps = builddeps.replace(' ', '')
builddeps = builddeps.split(',')
# Virtual packages not needed
builddeps_to_remove = ["debhelper-compat", "dh-sequence-python3"]
builddeps_to_remove = ['debhelper-compat', 'dh-sequence-python3']
builddeps = [x for x in builddeps if x not in builddeps_to_remove]
return builddeps
......@@ -79,12 +81,12 @@ def define_xml(pkgs_path, version):
def generate_xml(xml, version, headers, lib):
print(f'INFO: Generating {xml}...')
root = ET.Element("ABI_Descriptor")
ET.SubElement(root, "version").text = '\n'+version+'\n'
ET.SubElement(root, "headers").text = '\n'+'\n'.join(headers)+'\n'
ET.SubElement(root, "libs").text = '\n'+lib+'\n'
root = ET.Element('ABI_Descriptor')
ET.SubElement(root, 'version').text = '\n'+version+'\n'
ET.SubElement(root, 'headers').text = '\n'+'\n'.join(headers)+'\n'
ET.SubElement(root, 'libs').text = '\n'+lib+'\n'
tree = ET.ElementTree(root)
tree.write(xml, encoding="utf-8")
tree.write(xml, encoding='utf-8')
def remove_prefix(text, prefix):
......@@ -102,12 +104,35 @@ def remove_suffix(text, suffix):
def detect_libnames(path):
my_lib = list(pathlib.Path(path).glob('**/*.so'))
my_lib = [i.name for i in my_lib]
my_lib = [remove_prefix(i, "lib") for i in my_lib]
my_lib = [remove_suffix(i, ".so") for i in my_lib]
my_lib = [remove_prefix(i, 'lib') for i in my_lib]
my_lib = [remove_suffix(i, '.so') for i in my_lib]
return my_lib
def run_abi_checker(lib, xml_old, ver_old, xml_new, ver_new):
def detect_deb_arch(list_file):
arches = set()
for file in list_file:
my_deb = debfile.DebFile(file)
my_control = my_deb.debcontrol()
my_arch = my_control['Architecture']
arches.add(my_arch)
if 'all' in arches:
arches.remove('all')
if len(arches) == 0:
sys.exit('ERROR: no architecture-dependent package detected!\n' +
'ERROR: provided packages are architecture "all" only.')
if len(arches) != 1:
sys.exit('ERROR: several architectures have been detected: ' + str(arches) + '\n' +
'ERROR: abi-compliance-checker can analyze only one arch at once!')
else:
my_arch = next(iter(arches))
print(f'INFO: Architecture {my_arch} detected')
return my_arch
def run_abi_checker(lib, xml_old, ver_old, xml_new, ver_new, arch):
print('######################################################')
print(f'INFO: Running abi-compliance-checker to compare lib{lib}.so:')
print(f'INFO: - {ver_old}')
......@@ -115,9 +140,34 @@ def run_abi_checker(lib, xml_old, ver_old, xml_new, ver_new):
print(f'INFO: - {ver_new}')
print(f'INFO: -- {xml_new}')
print('######################################################')
acc_process = subprocess.run(['/usr/bin/abi-compliance-checker', '-lib', lib,
'-old', xml_old, '-v1', ver_old,
'-new', xml_new, '-v2', ver_new])
if arch == 'amd64':
crossbuild = ['--gcc-prefix', 'x86_64-linux-gnu',
'--gcc-path', '/usr/bin/x86_64-linux-gnu-gcc']
elif arch == 'arm64':
# abi-compliance-checker reports an "UNKNOWN" architecture instead of aarch64.
# This warning can be ignored as acc works correctly anyway.
crossbuild = ['--gcc-prefix', 'aarch64-linux-gnu',
'--gcc-path', '/usr/bin/aarch64-linux-gnu-gcc']
elif arch == 'armhf':
# abi-compliance-checker reports a wrongly warning about a mismatch
# between architectures of input objects and the used GCC.
# This warning can be ignored as acc works correctly anyway.
crossbuild = ['--gcc-prefix', 'arm-linux-gnueabihf',
'--gcc-path', '/usr/bin/arm-linux-gnueabihf-gcc']
else:
sys.exit('ERROR: unknown architecture detected: ' + arch)
# acc should be executed with admin rights to avoid "WARNING, can't find ldconfig"
# because ldconfig it located in /sbin/. However this warning can be ignored because
# acc uses linker to get custom system paths otherwise it uses default ones.
acc_cmd = ['/usr/bin/abi-compliance-checker']
acc_cmd.extend(crossbuild)
acc_cmd.extend(['--arch', arch, '-lib', lib,
'-old', xml_old, '-v1', ver_old,
'-new', xml_new, '-v2', ver_new])
acc_process = subprocess.run(acc_cmd)
sys.stdout.flush()
if acc_process.returncode == 0:
print('INFO: no ABI breakage detected!')
......@@ -128,7 +178,7 @@ def run_abi_checker(lib, xml_old, ver_old, xml_new, ver_new):
return acc_process.returncode
def abi_checker(lib_names_old, xml_descr_old, my_old_ver, lib_names_new, xml_descr_new, my_new_ver):
def abi_checker(lib_names_old, xml_descr_old, my_old_ver, lib_names_new, xml_descr_new, my_new_ver, arch):
acc_returncode = 0
for lib in lib_names_new:
my_lib = 'lib'+lib+'.so'
......@@ -145,13 +195,14 @@ def abi_checker(lib_names_old, xml_descr_old, my_old_ver, lib_names_new, xml_des
xml_old = xml
break
rac_returncode = run_abi_checker(lib, xml_old, my_old_ver, xml_new, my_new_ver)
rac_returncode = run_abi_checker(lib, xml_old, my_old_ver, xml_new, my_new_ver, arch)
if rac_returncode != 0:
acc_returncode = rac_returncode
else:
print(f'INFO: {my_lib} is not in the old package, no need to run abi-compliance-checker')
return acc_returncode
def main():
parser = argparse.ArgumentParser(
description='Check for ABI/API breakage between a new version and a former one')
......@@ -167,7 +218,7 @@ def main():
sys.exit('ERROR: abi-compliance-checker not found in /usr/bin/\n' +
'ERROR: abi-compliance-checker can be installed with: apt install abi-compliance-checker')
print(f"Checking for ABI/API breakage in {folder_bin}!")
print(f'Checking for ABI/API breakage in {folder_bin}!')
# Check if artifacts from a previous run are still there
folder_pbo = os.path.exists('pkg_binaries_old')
......@@ -179,7 +230,10 @@ def main():
'ERROR: \'pkg_binaries_old\', \'pkg_old_extracted\' and \'pkg_new_extracted\'')
# Extract debs of new version
extract_debs(folder_bin, 'pkg_new_extracted')
list_new_debs = extract_debs(folder_bin, 'pkg_new_extracted')
# Detect packages architecture
deb_arch = detect_deb_arch(list_new_debs)
# Read dsc of new version to retrieve old bin from apt
file_dsc = list(pathlib.Path(folder_bin).glob('*.dsc'))
......@@ -195,17 +249,21 @@ def main():
my_builddeps = clean_build_deps(my_dsc['Build-Depends'])
print("INFO: abi-compliance-checker requires having Build-Deps installed")
print("INFO: Trying to install them now:")
print('INFO: abi-compliance-checker requires having Build-Deps installed')
print('INFO: Trying to install them now:')
crossbuild = 'crossbuild-essential-' + deb_arch
my_builddeps.append(crossbuild)
print(my_builddeps)
subprocess.run(['sudo', '/usr/bin/dpkg', '--add-architecture', deb_arch])
subprocess.run(['sudo', '/usr/bin/apt', 'update'])
subprocess.run(['sudo', '/usr/bin/apt', 'install', '-y'] + my_builddeps)
# Download debs of old version
list_bin_deb = list(bin_deb_gen.split(", "))
list_bin_deb = list(bin_deb_gen.split(', '))
folder_old_bin = 'pkg_binaries_old'
os.mkdir(folder_old_bin)
for bin_deb in list_bin_deb:
bin_deb += ':' + deb_arch
print(bin_deb)
subprocess.run(['/usr/bin/apt', 'download', bin_deb],
cwd=folder_old_bin)
......@@ -224,7 +282,8 @@ def main():
# Check if library is in both the new and the old packages before running it
acc_returncode = abi_checker(lib_names_old, xml_descr_old, my_old_ver,
lib_names_new, xml_descr_new, my_new_ver)
lib_names_new, xml_descr_new, my_new_ver,
deb_arch)
sys.exit(acc_returncode)
......