diff --git a/.gitignore b/.gitignore index 35e5b6797..43c4115cf 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ **/CMakeCache.txt **/CMakeFiles build +checker diff --git a/checker/abi-suppr.txt b/checker/abi-suppr.txt deleted file mode 100644 index 98780dd1d..000000000 --- a/checker/abi-suppr.txt +++ /dev/null @@ -1,9 +0,0 @@ -# settings are opaque, ignore all changes -[suppress_type] -type_kind = struct -name = rdp_settings - -# allow insertions at end of structs -[suppress_type] -type_kind = struct -has_data_members_inserted_at = end diff --git a/checker/check-abi b/checker/check-abi deleted file mode 100755 index aa00a13c4..000000000 --- a/checker/check-abi +++ /dev/null @@ -1,282 +0,0 @@ -#!/usr/bin/python3 - -# SPDX-License-Identifier: GPL-3.0-or-later -# -# Copyright 2019 Mathieu Bridon -# Copyright 2021 Bastien Nocera - -"""check-abi""" - -import argparse -import contextlib -import glob -import os -import shutil -import subprocess -import sys - -VERSION = '0.1' - -def format_title(title): - """Put title in a box""" - box = { - 'tl': '╔', 'tr': '╗', 'bl': '╚', 'br': '╝', 'h': '═', 'v': '║', - } - hline = box['h'] * (len(title) + 2) - - return '\n'.join([ - f"{box['tl']}{hline}{box['tr']}", - f"{box['v']} {title} {box['v']}", - f"{box['bl']}{hline}{box['br']}", - ]) - - -def rm_rf(path): - """rm -rf""" - try: - shutil.rmtree(path) - except FileNotFoundError: - pass - - -def sanitize_path(name): - """Replace slashes with dashes""" - return name.replace('/', '-') - - -def get_current_revision(): - """gets the current git revision""" - revision = subprocess.check_output(['git', 'rev-parse', '--abbrev-ref', 'HEAD'], - encoding='utf-8').strip() - - if revision == 'HEAD': - # This is a detached HEAD, get the commit hash - revision = subprocess.check_output(['git', 'rev-parse', 'HEAD']).strip().decode('utf-8') - - return revision - - -def get_meson_version(): - """Retrieves the version of Meson as a tuple""" - res = subprocess.check_output(['meson', '--version']).strip().decode('utf-8') - return [int(x) for x in res.split('.')] - - -def build_meson(build_dir, parameters, env): - """Builds using Meson""" - _setup_args = ['meson', 'setup', build_dir, '--prefix=/usr', '--libdir=lib'] - meson_version = get_meson_version() - if meson_version[0] > 0 or (meson_version[0] == 0 and meson_version[1] >= 54): - _compile_args = ['meson', 'compile', '-v', '-C', build_dir] - else: - _compile_args = ['ninja', '-v', '-C', build_dir] - if meson_version[0] > 0 or (meson_version[0] == 0 and meson_version[1] >= 47): - _install_args = ['meson', 'install', '-C', build_dir] - else: - _install_args = ['ninja', '-v', '-C', build_dir, 'install'] - if parameters is not None: - _setup_args += parameters.split(' ') - subprocess.check_call(_setup_args) - subprocess.check_call(_compile_args) - subprocess.check_call(_install_args, env=env) - - -def get_cmake_version(): - """Retrieves the version of CMake as a tuple""" - res = subprocess.check_output(['cmake', '--version']).strip().decode('utf-8') - lines = res.split('\n') - ver = lines[0].replace('cmake version ', '') - return [int(x) for x in ver.split('.')] - - -def build_cmake(build_dir, parameters, env): - """Builds using CMake""" - _setup_args = [ - "cmake", - "-GNinja", - "-B", - build_dir, - "-S", - ".", - "-DCMAKE_INSTALL_PREFIX=/usr", - "-DCMAKE_INSTALL_LIBDIR=lib", - ] - _compile_args = ['cmake', '--build', build_dir] - _install_args = ['cmake', '--install', build_dir] - if parameters is not None: - _setup_args += parameters.split(' ') - subprocess.check_call(_setup_args) - subprocess.check_call(_compile_args) - subprocess.check_call(_install_args, env=env) - - -def build_autotools(revision, src_dir_copy, build_dir, parameters, env): - """Builds using Autotools""" - src_dir = os.getcwd() - - # Setup src dir copy - os.mkdir(src_dir_copy) - os.chdir(src_dir_copy) - subprocess.check_call(['git', 'clone', src_dir, '.']) - subprocess.check_call(['git', 'checkout', '-q', revision]) - subprocess.check_call(['sed', - '-i', - 's/AM_GNU_GETTEXT_VERSION.*/AM_GNU_GETTEXT_VERSION([0.21])/', - 'configure.ac']) - os.chdir('..') - - os.mkdir(build_dir) - os.chdir(build_dir) - autogen_path = src_dir_copy + '/autogen.sh' - _args = [autogen_path, '--prefix=/usr', '--libdir=/usr/lib'] - if parameters is not None: - _args += parameters.split(' ') - subprocess.check_call(_args) - subprocess.check_call(['make']) - subprocess.check_call(['make','install'], env=env) - os.chdir(src_dir) - - -@contextlib.contextmanager -def checkout_git_revision(revision): - """Checkout a git revision before reverting to the current one""" - current_revision = get_current_revision() - subprocess.check_call(['git', 'checkout', '-q', revision]) - - try: - yield - finally: - subprocess.check_call(['git', 'checkout', '-q', current_revision]) - - -def build_install(revision, build_system, parameters): - """Build git revision with the passed build system""" - build_dir = '_check_abi_build' - dest_dir = os.path.abspath(sanitize_path(revision)) - src_dir_copy = os.getcwd() + '/_src_copy' - if not args.quiet: - print(format_title(f'# Building and installing {revision} in {dest_dir}'), - end='\n\n', flush=True) - - with checkout_git_revision(revision): - rm_rf(build_dir) - rm_rf(revision) - rm_rf(src_dir_copy) - - env = os.environ.copy() - env['DESTDIR'] = dest_dir - env['V'] = '1' - - if not build_system or build_system == 'autodetect': - if os.path.exists('meson.build'): - build_system = 'meson' - elif os.path.exists('CMakeLists.txt'): - build_system = 'cmake' - elif os.path.exists('configure.ac') and os.path.exists('autogen.sh'): - build_system = 'autotools' - else: - print('Could not detect build system', file=sys.stderr) - assert() - - if build_system == 'meson': - build_meson(build_dir, parameters, env) - elif build_system == 'cmake': - build_cmake(build_dir, parameters, env) - elif build_system == 'autotools': - build_autotools(revision, src_dir_copy, build_dir, parameters, env) - else: - print(f'Unsupported build system "f{build_system}"', file=sys.stderr) - assert() - - return dest_dir - - -def compare(_old_tree, _new_tree): - """Compare the ABIs between 2 build trees""" - if not args.quiet: - print(format_title('# Comparing the two ABIs'), end='\n\n', flush=True) - - if not args.library_name: - paths = glob.glob(os.path.join(_old_tree, 'usr', 'lib') + '/*.so') - libs_name = [] - for path in paths: - libs_name.append(os.path.basename(path)) - else: - libs_name = [ args.library_name ] - - for lib_name in libs_name: - - old_headers = os.path.join(_old_tree, 'usr', 'include') - old_lib = os.path.join(_old_tree, 'usr', 'lib', lib_name) - - new_headers = os.path.join(_new_tree, 'usr', 'include') - new_lib = os.path.join(_new_tree, 'usr', 'lib', lib_name) - - cmd = [ - 'abidiff', '--headers-dir1', old_headers, '--headers-dir2', new_headers, - '--drop-private-types', '--fail-no-debug-info', '--no-added-syms' - ] - if args.suppr: - cmd.append ('--suppr') - cmd.append (args.suppr) - - cmd.append (old_lib) - cmd.append (new_lib) - - subprocess.check_call(cmd) - - -if __name__ == '__main__': - parser = argparse.ArgumentParser() - - parser.add_argument('old', help='the previous git revision, considered the reference') - parser.add_argument('new', help='the new git revision, to compare to the reference') - parser.add_argument('-q', '--quiet', action='store_true', help='increase output verbosity') - parser.add_argument('-s', '--suppr', help='Pass a suppression file to abidiff') - parser.add_argument('--old-build-system', - help='build system to use for the reference git revision (default: autodetect)', - type=str, choices=['autodetect', 'meson', 'cmake', 'autotools']) - parser.add_argument('--new-build-system', - help='build system to use for the new git revision (default: autodetect)', - type=str, choices=['autodetect', 'meson', 'cmake', 'autotools']) - parser.add_argument('--old-parameters', - help='additional arguments to pass to the reference git revisionʼs build system', - type=str) - parser.add_argument('--new-parameters', - help='additional arguments to pass to the new git revisionʼs build system', - type=str) - parser.add_argument('--parameters', - help="additional arguments to pass to both the old and the" - " new git revisionʼs build systems", - type=str) - parser.add_argument('-l', '--library-name', - help='the name of the shared library to compare (default: \'*.so\')', - type=str) - - args = parser.parse_args() - - if args.parameters: - if args.old_parameters or args.new_parameters: - if not args.quiet: - print("Can't pass --parameters with either --old-parameters" - " or --new-parameters") - sys.exit(1) - args.old_parameters = args.parameters - args.new_parameters = args.parameters - - if args.old == args.new and args.old_parameters == args.new_parameters: - if not args.quiet: - print("Let's not waste time comparing something to itself") - sys.exit(0) - - old_tree = build_install(args.old, args.old_build_system, args.old_parameters) - new_tree = build_install(args.new, args.new_build_system, args.new_parameters) - - try: - compare(old_tree, new_tree) - - except Exception: # pylint: disable=broad-except - sys.exit(1) - - if not args.quiet: - print(f'Hurray! {args.old} and {args.new} are ABI-compatible!') \ No newline at end of file