"""Require the shared library to export exactly the public header functions.""" import argparse from pathlib import Path import re import subprocess def main(): parser = argparse.ArgumentParser(description=__doc__) parser.add_argument('--allow-export', action='append', default=[]) parser.add_argument('nm') parser.add_argument('library') parser.add_argument('headers', nargs='+') args = parser.parse_args() declarations = re.compile( r"^[^\n;{}]*\b(yasl_\w+)\s*\([^;{}]*\);", re.MULTILINE ) expected = set() for header in args.headers: source = re.sub(r"/\*.*?\*/|//[^\n]*", "", Path(header).read_text(), flags=re.DOTALL) expected.update(declarations.findall(source)) if not expected: raise SystemExit("No public function declarations found") output = subprocess.check_output( [args.nm, "-D", "--defined-only", "--format=posix", args.library], text=True ) exported = {line.split()[0] for line in output.splitlines() if line.strip()} missing = expected - exported leaked = exported - expected - set(args.allow_export) if missing or leaked: if missing: print("Missing public exports:", ", ".join(sorted(missing))) if leaked: print("Unexpected exports:", ", ".join(sorted(leaked))) raise SystemExit(1) print(f"Verified {len(expected)} public exports") if __name__ == "__main__": main()