diff options
-rwxr-xr-x | .ci/check-abi | 115 | ||||
-rw-r--r-- | .gitlab-ci.yml | 7 |
2 files changed, 120 insertions, 2 deletions
diff --git a/.ci/check-abi b/.ci/check-abi new file mode 100755 index 0000000..f511e10 --- /dev/null +++ b/.ci/check-abi @@ -0,0 +1,115 @@ +#!/usr/bin/python3 + + +import argparse +import contextlib +import os +import shutil +import subprocess +import sys + + +def format_title(title): + 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): + try: + shutil.rmtree(path) + except FileNotFoundError: + pass + + +def sanitize_path(name): + return name.replace('/', '-') + + +def get_current_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 + + +@contextlib.contextmanager +def checkout_git_revision(revision): + 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_dir = '_build' + dest_dir = os.path.abspath(sanitize_path(revision)) + 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) + + subprocess.check_call(['./autogen.sh', + '--prefix=/usr', + '--libdir=/usr/lib/', + '--disable-gtk-doc', + '--disable-umockdev']) + subprocess.check_call(['make']) + subprocess.check_call(['make', 'install'], + env={'DESTDIR': dest_dir}) + + return dest_dir + + +def compare(old_tree, new_tree): + print(format_title(f'# Comparing the two ABIs'), end='\n\n', flush=True) + + old_headers = os.path.join(old_tree, 'usr', 'include') + old_lib = os.path.join(old_tree, 'usr', 'lib', 'libgudev-1.0.so') + + new_headers = os.path.join(new_tree, 'usr', 'include') + new_lib = os.path.join(new_tree, 'usr', 'lib', 'libgudev-1.0.so') + + subprocess.check_call([ + 'abidiff', '--headers-dir1', old_headers, '--headers-dir2', new_headers, + '--drop-private-types', '--fail-no-debug-info', '--no-added-syms', old_lib, new_lib]) + + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + + parser.add_argument('old', help='the previous revision, considered the reference') + parser.add_argument('new', help='the new revision, to compare to the reference') + + args = parser.parse_args() + + if args.old == args.new: + print("Let's not waste time comparing something to itself") + sys.exit(0) + + old_tree = build_install(args.old) + new_tree = build_install(args.new) + + try: + compare(old_tree, new_tree) + + except Exception: + sys.exit(1) + + print(f'Hurray! {args.old} and {args.new} are ABI-compatible!') diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index fa5cc5f..763c5cc 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,3 +1,6 @@ +variables: + LAST_ABI_BREAK: "43a593b5b4097b887e49eaacafbc1337bd709718" + stages: - test @@ -5,10 +8,10 @@ build-fedora: image: fedora:latest stage: test before_script: - - dnf install -y gcc redhat-rpm-config libtool automake autoconf gtk-doc make glib2-devel systemd-devel umockdev-devel + - dnf install -y gcc redhat-rpm-config libtool automake autoconf gtk-doc make glib2-devel systemd-devel umockdev-devel git libabigail gnome-common script: - ./autogen.sh --disable-dependency-tracking - make - make install - make check - + - ./.ci/check-abi ${LAST_ABI_BREAK} $(git rev-parse HEAD) |