#!/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(['meson', build_dir, '--prefix=/usr', '--libdir=lib', '-Dx11-examples=false', '-Ddoc=false', '-Dgtk-examples=false']) subprocess.check_call(['ninja', '-v', '-C', build_dir]) subprocess.check_call(['ninja', '-v', '-C', build_dir, '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', 'libfprint.so') new_headers = os.path.join(new_tree, 'usr', 'include') new_lib = os.path.join(new_tree, 'usr', 'lib', 'libfprint.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!')