-
Notifications
You must be signed in to change notification settings - Fork 318
/
Copy pathpa_compare_def_files.py
98 lines (84 loc) · 3.17 KB
/
pa_compare_def_files.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# PortAudio Repository .def file checker
#
# Run this script from the root of the repository using the command:
# python pa_compare_def_files.py
#
# The PortAudio repository contains two (semi-redundant) .def
# files that specify exported symbols for Windows dynamic link libraries.
#
# This script checks that the two .def files export the same symbols
# using the same ordinals.
#
# The .def files are:
#
# 1. msvc/portaudio.def
# 2. cmake/portaudio.def.in
#
# The CMake .def.in file is an input that generates a .def file
# with host-api-specific symbols commented out when a particular host API
# is not built.
import sys
msvc_portaudio_def_path = "msvc/portaudio.def"
cmake_portaudio_def_in_path = "cmake/portaudio.def.in"
def parse_def_file(file):
result = {}
for line in file:
line = line.strip()
if line:
if "EXPORTS" in line or line[0] == ";":
continue
columns = line.split()
#print(columns)
symbol, ordinal = columns
#print(symbol, ordinal)
if ordinal in result:
print(f"error: ordinal {ordinal} referenced multiple times")
result[ordinal] = symbol
return result
with open(msvc_portaudio_def_path, mode="rt", encoding="utf-8") as msvc_portaudio_def:
msvc_portaudio_def_syms = parse_def_file(msvc_portaudio_def)
with open(cmake_portaudio_def_in_path, mode="rt", encoding="utf-8") as cmake_portaudio_def_in:
cmake_portaudio_def_in_syms = parse_def_file(cmake_portaudio_def_in)
def clear_cmake_exclude_condition_prefix(sym):
if "@" in sym:
return sym.split("@")[-1]
else:
return sym
# dictionary keys are the ordinals
ordinals = list(set(msvc_portaudio_def_syms.keys()).union(cmake_portaudio_def_in_syms.keys()))
ordinals.sort(key=lambda s: int(s.replace("@", "")))
msvcMissingCount = 0
cmakeMissingCount = 0
differenceCount = 0
print("ordinal, msvc, cmake, remark")
for ordinal in ordinals:
msvc_sym = msvc_portaudio_def_syms[ordinal] if ordinal in msvc_portaudio_def_syms else ""
cmake_sym = cmake_portaudio_def_in_syms[ordinal] if ordinal in cmake_portaudio_def_in_syms else ""
cmake_sym_no_cond = clear_cmake_exclude_condition_prefix(cmake_sym)
remark = ""
if not msvc_sym:
remark = "missing in msvc/portaudio.def"
msvcMissingCount += msvcMissingCount
elif not cmake_sym:
remark = "missing in cmake/portaudio.def.in"
cmakeMissingCount += cmakeMissingCount
elif msvc_sym != cmake_sym_no_cond:
remark = "differs"
differenceCount += 1
else:
remark = "ok"
print(f"{ordinal}, {msvc_sym}, {cmake_sym}, {remark}")
print("SUMMARY")
print("=======")
issuesFound = msvcMissingCount > 0 or cmakeMissingCount > 0 or differenceCount > 0
if msvcMissingCount > 0:
print(f"error: {msvc_portaudio_def_path} ({msvcMissingCount} missing symbols)")
if cmakeMissingCount > 0:
print(f"error: {cmake_portaudio_def_in_path} ({cmakeMissingCount} missing symbols)")
if differenceCount > 0:
print(f"error: there are {differenceCount} ordinals with non-matching symbols")
if issuesFound:
sys.exit(1)
else:
print("No issues found. All good.")
sys.exit(0)