10b37f209SEric Fiselier#!/usr/bin/env python 20b37f209SEric Fiselier# ===----------------------------------------------------------------------===## 30b37f209SEric Fiselier# 457b08b09SChandler Carruth# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 557b08b09SChandler Carruth# See https://llvm.org/LICENSE.txt for license information. 657b08b09SChandler Carruth# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 70b37f209SEric Fiselier# 80b37f209SEric Fiselier# ===----------------------------------------------------------------------===## 90b37f209SEric Fiselier""" 100b37f209SEric Fiseliersym_diff - Compare two symbol lists and output the differences. 110b37f209SEric Fiselier""" 120b37f209SEric Fiselier 130b37f209SEric Fiselierfrom argparse import ArgumentParser 140b37f209SEric Fiselierimport sys 150b37f209SEric Fiselierfrom libcxx.sym_check import diff, util 160b37f209SEric Fiselier 170b37f209SEric Fiselier 180b37f209SEric Fiselierdef main(): 190b37f209SEric Fiselier parser = ArgumentParser( 20*7bfaa0f0STobias Hieta description="Extract a list of symbols from a shared library." 21*7bfaa0f0STobias Hieta ) 220b37f209SEric Fiselier parser.add_argument( 23*7bfaa0f0STobias Hieta "--names-only", 24*7bfaa0f0STobias Hieta dest="names_only", 25*7bfaa0f0STobias Hieta help="Only print symbol names", 26*7bfaa0f0STobias Hieta action="store_true", 27*7bfaa0f0STobias Hieta default=False, 28*7bfaa0f0STobias Hieta ) 290b37f209SEric Fiselier parser.add_argument( 30*7bfaa0f0STobias Hieta "--removed-only", 31*7bfaa0f0STobias Hieta dest="removed_only", 32*7bfaa0f0STobias Hieta help="Only print removed symbols", 33*7bfaa0f0STobias Hieta action="store_true", 34*7bfaa0f0STobias Hieta default=False, 35*7bfaa0f0STobias Hieta ) 36*7bfaa0f0STobias Hieta parser.add_argument( 37*7bfaa0f0STobias Hieta "--only-stdlib-symbols", 38*7bfaa0f0STobias Hieta dest="only_stdlib", 390b37f209SEric Fiselier help="Filter all symbols not related to the stdlib", 40*7bfaa0f0STobias Hieta action="store_true", 41*7bfaa0f0STobias Hieta default=False, 42*7bfaa0f0STobias Hieta ) 430b37f209SEric Fiselier parser.add_argument( 44*7bfaa0f0STobias Hieta "--strict", 45*7bfaa0f0STobias Hieta dest="strict", 46*7bfaa0f0STobias Hieta help="Exit with a non-zero status if any symbols " "differ", 47*7bfaa0f0STobias Hieta action="store_true", 48*7bfaa0f0STobias Hieta default=False, 49*7bfaa0f0STobias Hieta ) 500b37f209SEric Fiselier parser.add_argument( 51*7bfaa0f0STobias Hieta "-o", 52*7bfaa0f0STobias Hieta "--output", 53*7bfaa0f0STobias Hieta dest="output", 54*7bfaa0f0STobias Hieta help="The output file. stdout is used if not given", 55*7bfaa0f0STobias Hieta type=str, 56*7bfaa0f0STobias Hieta action="store", 57*7bfaa0f0STobias Hieta default=None, 58*7bfaa0f0STobias Hieta ) 590b37f209SEric Fiselier parser.add_argument( 60*7bfaa0f0STobias Hieta "--demangle", dest="demangle", action="store_true", default=False 61*7bfaa0f0STobias Hieta ) 620b37f209SEric Fiselier parser.add_argument( 63*7bfaa0f0STobias Hieta "old_syms", 64*7bfaa0f0STobias Hieta metavar="old-syms", 65*7bfaa0f0STobias Hieta type=str, 66*7bfaa0f0STobias Hieta help="The file containing the old symbol list or a library", 67*7bfaa0f0STobias Hieta ) 68*7bfaa0f0STobias Hieta parser.add_argument( 69*7bfaa0f0STobias Hieta "new_syms", 70*7bfaa0f0STobias Hieta metavar="new-syms", 71*7bfaa0f0STobias Hieta type=str, 72*7bfaa0f0STobias Hieta help="The file containing the new symbol list or a library", 73*7bfaa0f0STobias Hieta ) 740b37f209SEric Fiselier args = parser.parse_args() 750b37f209SEric Fiselier 760b37f209SEric Fiselier old_syms_list = util.extract_or_load(args.old_syms) 770b37f209SEric Fiselier new_syms_list = util.extract_or_load(args.new_syms) 780b37f209SEric Fiselier 790b37f209SEric Fiselier if args.only_stdlib: 800b37f209SEric Fiselier old_syms_list, _ = util.filter_stdlib_symbols(old_syms_list) 810b37f209SEric Fiselier new_syms_list, _ = util.filter_stdlib_symbols(new_syms_list) 820b37f209SEric Fiselier 830b37f209SEric Fiselier added, removed, changed = diff.diff(old_syms_list, new_syms_list) 840b37f209SEric Fiselier if args.removed_only: 850b37f209SEric Fiselier added = {} 860b37f209SEric Fiselier report, is_break, is_different = diff.report_diff( 87*7bfaa0f0STobias Hieta added, removed, changed, names_only=args.names_only, demangle=args.demangle 88*7bfaa0f0STobias Hieta ) 890b37f209SEric Fiselier if args.output is None: 900b37f209SEric Fiselier print(report) 910b37f209SEric Fiselier else: 92*7bfaa0f0STobias Hieta with open(args.output, "w") as f: 93*7bfaa0f0STobias Hieta f.write(report + "\n") 940b37f209SEric Fiselier exit_code = 1 if is_break or (args.strict and is_different) else 0 950b37f209SEric Fiselier sys.exit(exit_code) 960b37f209SEric Fiselier 97*7bfaa0f0STobias Hieta 98*7bfaa0f0STobias Hietaif __name__ == "__main__": 990b37f209SEric Fiselier main() 100