12d9feb59f05b62531bd8070b41615da5df15d67dEric Fiselier#!/usr/bin/env python
2a9e91f30eea39e57e4d9cd0067f6a5f10a64c2ebEric Fiselier#===----------------------------------------------------------------------===##
3a9e91f30eea39e57e4d9cd0067f6a5f10a64c2ebEric Fiselier#
4a9e91f30eea39e57e4d9cd0067f6a5f10a64c2ebEric Fiselier#                     The LLVM Compiler Infrastructure
5a9e91f30eea39e57e4d9cd0067f6a5f10a64c2ebEric Fiselier#
6a9e91f30eea39e57e4d9cd0067f6a5f10a64c2ebEric Fiselier# This file is dual licensed under the MIT and the University of Illinois Open
7a9e91f30eea39e57e4d9cd0067f6a5f10a64c2ebEric Fiselier# Source Licenses. See LICENSE.TXT for details.
8a9e91f30eea39e57e4d9cd0067f6a5f10a64c2ebEric Fiselier#
9a9e91f30eea39e57e4d9cd0067f6a5f10a64c2ebEric Fiselier#===----------------------------------------------------------------------===##
102d9feb59f05b62531bd8070b41615da5df15d67dEric Fiselier"""
112d9feb59f05b62531bd8070b41615da5df15d67dEric Fiseliersym_diff - Compare two symbol lists and output the differences.
122d9feb59f05b62531bd8070b41615da5df15d67dEric Fiselier"""
13a9e91f30eea39e57e4d9cd0067f6a5f10a64c2ebEric Fiselier
142d9feb59f05b62531bd8070b41615da5df15d67dEric Fiselierfrom argparse import ArgumentParser
152d9feb59f05b62531bd8070b41615da5df15d67dEric Fiselierimport sys
161147753b1ccb0bbc40d05e7e73089e2b7bb38317Eric Fiselierfrom libcxx.sym_check import diff, util
172d9feb59f05b62531bd8070b41615da5df15d67dEric Fiselier
182d9feb59f05b62531bd8070b41615da5df15d67dEric Fiselier
192d9feb59f05b62531bd8070b41615da5df15d67dEric Fiselierdef main():
202d9feb59f05b62531bd8070b41615da5df15d67dEric Fiselier    parser = ArgumentParser(
212d9feb59f05b62531bd8070b41615da5df15d67dEric Fiselier        description='Extract a list of symbols from a shared library.')
222d9feb59f05b62531bd8070b41615da5df15d67dEric Fiselier    parser.add_argument(
232d9feb59f05b62531bd8070b41615da5df15d67dEric Fiselier        '--names-only', dest='names_only',
242d9feb59f05b62531bd8070b41615da5df15d67dEric Fiselier        help='Only print symbol names',
252d9feb59f05b62531bd8070b41615da5df15d67dEric Fiselier        action='store_true', default=False)
262d9feb59f05b62531bd8070b41615da5df15d67dEric Fiselier    parser.add_argument(
276dbed46df6689870629b7bbe7add7018dce19aa0Eric Fiselier        '--removed-only', dest='removed_only',
286dbed46df6689870629b7bbe7add7018dce19aa0Eric Fiselier        help='Only print removed symbols',
296dbed46df6689870629b7bbe7add7018dce19aa0Eric Fiselier        action='store_true', default=False)
300d6941834cb62a02deed43af20d24cc2a10e8acbEric Fiselier    parser.add_argument('--only-stdlib-symbols', dest='only_stdlib',
310d6941834cb62a02deed43af20d24cc2a10e8acbEric Fiselier                        help="Filter all symbols not related to the stdlib",
320d6941834cb62a02deed43af20d24cc2a10e8acbEric Fiselier                        action='store_true', default=False)
3308305aaf6e3012b4a3080ea84d966d0dfdc736adEric Fiselier    parser.add_argument('--strict', dest='strict',
3408305aaf6e3012b4a3080ea84d966d0dfdc736adEric Fiselier                        help="Exit with a non-zero status if any symbols "
3508305aaf6e3012b4a3080ea84d966d0dfdc736adEric Fiselier                             "differ",
3608305aaf6e3012b4a3080ea84d966d0dfdc736adEric Fiselier                        action='store_true', default=False)
376dbed46df6689870629b7bbe7add7018dce19aa0Eric Fiselier    parser.add_argument(
382d9feb59f05b62531bd8070b41615da5df15d67dEric Fiselier        '-o', '--output', dest='output',
392d9feb59f05b62531bd8070b41615da5df15d67dEric Fiselier        help='The output file. stdout is used if not given',
402d9feb59f05b62531bd8070b41615da5df15d67dEric Fiselier        type=str, action='store', default=None)
412d9feb59f05b62531bd8070b41615da5df15d67dEric Fiselier    parser.add_argument(
422d9feb59f05b62531bd8070b41615da5df15d67dEric Fiselier        '--demangle', dest='demangle', action='store_true', default=False)
432d9feb59f05b62531bd8070b41615da5df15d67dEric Fiselier    parser.add_argument(
442d9feb59f05b62531bd8070b41615da5df15d67dEric Fiselier        'old_syms', metavar='old-syms', type=str,
452d9feb59f05b62531bd8070b41615da5df15d67dEric Fiselier        help='The file containing the old symbol list or a library')
462d9feb59f05b62531bd8070b41615da5df15d67dEric Fiselier    parser.add_argument(
472d9feb59f05b62531bd8070b41615da5df15d67dEric Fiselier        'new_syms', metavar='new-syms', type=str,
482d9feb59f05b62531bd8070b41615da5df15d67dEric Fiselier        help='The file containing the new symbol list or a library')
492d9feb59f05b62531bd8070b41615da5df15d67dEric Fiselier    args = parser.parse_args()
502d9feb59f05b62531bd8070b41615da5df15d67dEric Fiselier
512d9feb59f05b62531bd8070b41615da5df15d67dEric Fiselier    old_syms_list = util.extract_or_load(args.old_syms)
522d9feb59f05b62531bd8070b41615da5df15d67dEric Fiselier    new_syms_list = util.extract_or_load(args.new_syms)
532d9feb59f05b62531bd8070b41615da5df15d67dEric Fiselier
540d6941834cb62a02deed43af20d24cc2a10e8acbEric Fiselier    if args.only_stdlib:
550d6941834cb62a02deed43af20d24cc2a10e8acbEric Fiselier        old_syms_list, _ = util.filter_stdlib_symbols(old_syms_list)
560d6941834cb62a02deed43af20d24cc2a10e8acbEric Fiselier        new_syms_list, _ = util.filter_stdlib_symbols(new_syms_list)
570d6941834cb62a02deed43af20d24cc2a10e8acbEric Fiselier
582d9feb59f05b62531bd8070b41615da5df15d67dEric Fiselier    added, removed, changed = diff.diff(old_syms_list, new_syms_list)
596dbed46df6689870629b7bbe7add7018dce19aa0Eric Fiselier    if args.removed_only:
606dbed46df6689870629b7bbe7add7018dce19aa0Eric Fiselier        added = {}
6108305aaf6e3012b4a3080ea84d966d0dfdc736adEric Fiselier    report, is_break, is_different = diff.report_diff(
6208305aaf6e3012b4a3080ea84d966d0dfdc736adEric Fiselier        added, removed, changed, names_only=args.names_only,
6308305aaf6e3012b4a3080ea84d966d0dfdc736adEric Fiselier        demangle=args.demangle)
642d9feb59f05b62531bd8070b41615da5df15d67dEric Fiselier    if args.output is None:
652d9feb59f05b62531bd8070b41615da5df15d67dEric Fiselier        print(report)
662d9feb59f05b62531bd8070b41615da5df15d67dEric Fiselier    else:
672d9feb59f05b62531bd8070b41615da5df15d67dEric Fiselier        with open(args.output, 'w') as f:
682d9feb59f05b62531bd8070b41615da5df15d67dEric Fiselier            f.write(report + '\n')
6908305aaf6e3012b4a3080ea84d966d0dfdc736adEric Fiselier    exit_code = 1 if is_break or (args.strict and is_different) else 0
7008305aaf6e3012b4a3080ea84d966d0dfdc736adEric Fiselier    sys.exit(exit_code)
712d9feb59f05b62531bd8070b41615da5df15d67dEric Fiselier
722d9feb59f05b62531bd8070b41615da5df15d67dEric Fiselierif __name__ == '__main__':
732d9feb59f05b62531bd8070b41615da5df15d67dEric Fiselier    main()
74