xref: /llvm-project/libcxx/utils/sym_diff.py (revision 7bfaa0f09d0564f315ea778023b34b8a113ec740)
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