[Workflow] Try to fix code-formatter failing to find changes in some cases.
[llvm-project.git] / lldb / scripts / verify_api.py
blob9d14a58121bfbc8c5afd66a71e4ce9d887525ac0
1 #!/usr/bin/env python
3 import subprocess
4 import optparse
5 import os
6 import os.path
7 import re
8 import sys
11 def extract_exe_symbol_names(arch, exe_path, match_str):
12 command = 'dsymutil --arch %s -s "%s" | grep "%s" | colrm 1 69' % (
13 arch,
14 exe_path,
15 match_str,
17 (command_exit_status, command_output) = subprocess.getstatusoutput(command)
18 if command_exit_status == 0:
19 if command_output:
20 return command_output[0:-1].split("'\n")
21 else:
22 print("error: command returned no output")
23 else:
24 print(
25 "error: command failed with exit status %i\n command: %s"
26 % (command_exit_status, command)
28 return list()
31 def verify_api(all_args):
32 """Verify the API in the specified library is valid given one or more binaries."""
33 usage = "usage: verify_api --library <path> [ --library <path> ...] executable1 [executable2 ...]"
34 description = """Verify the API in the specified library is valid given one or more binaries.
36 Example:
38 verify_api.py --library ~/Documents/src/lldb/build/Debug/LLDB.framework/LLDB --arch x86_64 /Applications/Xcode.app/Contents/PlugIns/DebuggerLLDB.ideplugin/Contents/MacOS/DebuggerLLDB --api-regex lldb
39 """
40 parser = optparse.OptionParser(
41 description=description, prog="verify_api", usage=usage
43 parser.add_option(
44 "-v",
45 "--verbose",
46 action="store_true",
47 dest="verbose",
48 help="display verbose debug info",
49 default=False,
51 parser.add_option(
52 "-a",
53 "--arch",
54 type="string",
55 action="append",
56 dest="archs",
57 help="architecture to use when checking the api",
59 parser.add_option(
60 "-r",
61 "--api-regex",
62 type="string",
63 dest="api_regex_str",
64 help="Exclude any undefined symbols that do not match this regular expression when searching for missing APIs.",
66 parser.add_option(
67 "-l",
68 "--library",
69 type="string",
70 action="append",
71 dest="libraries",
72 help="Specify one or more libraries that will contain all needed APIs for the executables.",
74 (options, args) = parser.parse_args(all_args)
76 api_external_symbols = list()
77 if options.archs:
78 for arch in options.archs:
79 for library in options.libraries:
80 external_symbols = extract_exe_symbol_names(
81 arch, library, "( SECT EXT)"
83 if external_symbols:
84 for external_symbol in external_symbols:
85 api_external_symbols.append(external_symbol)
86 else:
87 sys.exit(1)
88 else:
89 print("error: must specify one or more architectures with the --arch option")
90 sys.exit(4)
91 if options.verbose:
92 print("API symbols:")
93 for i, external_symbol in enumerate(api_external_symbols):
94 print("[%u] %s" % (i, external_symbol))
96 api_regex = None
97 if options.api_regex_str:
98 api_regex = re.compile(options.api_regex_str)
100 for arch in options.archs:
101 for exe_path in args:
102 print('Verifying (%s) "%s"...' % (arch, exe_path))
103 exe_errors = 0
104 undefined_symbols = extract_exe_symbol_names(
105 arch, exe_path, "( UNDF EXT)"
107 for undefined_symbol in undefined_symbols:
108 if api_regex:
109 match = api_regex.search(undefined_symbol)
110 if not match:
111 if options.verbose:
112 print("ignoring symbol: %s" % (undefined_symbol))
113 continue
114 if undefined_symbol in api_external_symbols:
115 if options.verbose:
116 print("verified symbol: %s" % (undefined_symbol))
117 else:
118 print("missing symbol: %s" % (undefined_symbol))
119 exe_errors += 1
120 if exe_errors:
121 print(
122 "error: missing %u API symbols from %s"
123 % (exe_errors, options.libraries)
125 else:
126 print("success")
129 if __name__ == "__main__":
130 verify_api(sys.argv[1:])