1#!/usr/bin/env python 2# ===----------------------------------------------------------------------===## 3# 4# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5# See https://llvm.org/LICENSE.txt for license information. 6# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7# 8# ===----------------------------------------------------------------------===## 9""" 10sym_diff - Compare two symbol lists and output the differences. 11""" 12 13from argparse import ArgumentParser 14import sys 15from libcxx.sym_check import diff, util 16 17 18def main(): 19 parser = ArgumentParser( 20 description="Extract a list of symbols from a shared library." 21 ) 22 parser.add_argument( 23 "--names-only", 24 dest="names_only", 25 help="Only print symbol names", 26 action="store_true", 27 default=False, 28 ) 29 parser.add_argument( 30 "--removed-only", 31 dest="removed_only", 32 help="Only print removed symbols", 33 action="store_true", 34 default=False, 35 ) 36 parser.add_argument( 37 "--only-stdlib-symbols", 38 dest="only_stdlib", 39 help="Filter all symbols not related to the stdlib", 40 action="store_true", 41 default=False, 42 ) 43 parser.add_argument( 44 "--strict", 45 dest="strict", 46 help="Exit with a non-zero status if any symbols " "differ", 47 action="store_true", 48 default=False, 49 ) 50 parser.add_argument( 51 "-o", 52 "--output", 53 dest="output", 54 help="The output file. stdout is used if not given", 55 type=str, 56 action="store", 57 default=None, 58 ) 59 parser.add_argument( 60 "--demangle", dest="demangle", action="store_true", default=False 61 ) 62 parser.add_argument( 63 "old_syms", 64 metavar="old-syms", 65 type=str, 66 help="The file containing the old symbol list or a library", 67 ) 68 parser.add_argument( 69 "new_syms", 70 metavar="new-syms", 71 type=str, 72 help="The file containing the new symbol list or a library", 73 ) 74 args = parser.parse_args() 75 76 old_syms_list = util.extract_or_load(args.old_syms) 77 new_syms_list = util.extract_or_load(args.new_syms) 78 79 if args.only_stdlib: 80 old_syms_list, _ = util.filter_stdlib_symbols(old_syms_list) 81 new_syms_list, _ = util.filter_stdlib_symbols(new_syms_list) 82 83 added, removed, changed = diff.diff(old_syms_list, new_syms_list) 84 if args.removed_only: 85 added = {} 86 report, is_break, is_different = diff.report_diff( 87 added, removed, changed, names_only=args.names_only, demangle=args.demangle 88 ) 89 if args.output is None: 90 print(report) 91 else: 92 with open(args.output, "w") as f: 93 f.write(report + "\n") 94 exit_code = 1 if is_break or (args.strict and is_different) else 0 95 sys.exit(exit_code) 96 97 98if __name__ == "__main__": 99 main() 100