Skip to content

Commit f294df2

Browse files
committed
TOOLS/dylib_unhell.py: simplify the otool output processing
There is no need to pipe things through shell and grep/awk, python is perfectly fine word processor. This makes it simpler to reason what is extracted and from where and also makes the script faster as we spawn only single process directly, not shell with multiple children.
1 parent c865008 commit f294df2

1 file changed

Lines changed: 26 additions & 35 deletions

File tree

TOOLS/dylib_unhell.py

Lines changed: 26 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
import shutil
77
import subprocess
88
import sys
9-
from functools import partial
109

1110
sys_re = re.compile("^/System")
1211
usr_re = re.compile("^/usr/lib/")
@@ -25,9 +24,16 @@ def is_user_lib(objfile, libname):
2524
"libswift" not in libname
2625

2726
def otool(objfile, rapths):
28-
command = f"otool -L '{objfile}' | grep -e '\t' | awk '{{ print $1 }}'"
29-
output = subprocess.check_output(command, shell=True, universal_newlines=True)
30-
libs = set(filter(partial(is_user_lib, objfile), output.split()))
27+
output = subprocess.check_output(
28+
["otool", "-L", objfile], universal_newlines=True,
29+
)
30+
libs = set()
31+
for line in output.splitlines():
32+
if not line.startswith("\t"):
33+
continue
34+
lib = line.split()[0]
35+
if is_user_lib(objfile, lib):
36+
libs.add(lib)
3137

3238
libs_resolved = set()
3339
libs_relative = set()
@@ -39,41 +45,27 @@ def otool(objfile, rapths):
3945

4046
return libs_resolved, libs_relative
4147

42-
def get_rapths(objfile):
43-
rpaths: list[str] = []
44-
command = f"otool -l '{objfile}' | grep -A2 LC_RPATH | grep path"
48+
def iter_rpaths(objfile):
49+
output = subprocess.check_output(
50+
["otool", "-l", objfile], universal_newlines=True,
51+
)
4552
path_re = re.compile(r"^\s*path (.*) \(offset \d*\)$")
53+
for line in output.splitlines():
54+
if match := path_re.match(line):
55+
yield match.group(1).strip()
4656

47-
try:
48-
result = subprocess.check_output(command, shell=True, universal_newlines=True)
49-
except Exception:
50-
return rpaths
51-
52-
for line in result.splitlines():
53-
match = path_re.search(line)
54-
if match is None:
55-
continue
56-
line_clean = match.group(1).strip()
57+
def get_rapths(objfile):
58+
loader_path = os.path.dirname(objfile)
59+
return [
5760
# resolve @loader_path
58-
if line_clean.startswith("@loader_path/"):
59-
line_clean = line_clean[len("@loader_path/"):]
60-
line_clean = os.path.join(os.path.dirname(objfile), line_clean)
61-
line_clean = os.path.normpath(line_clean)
62-
rpaths.append(line_clean)
63-
64-
return rpaths
61+
os.path.normpath(rpath.replace("@loader_path", loader_path, 1))
62+
for rpath in iter_rpaths(objfile)
63+
]
6564

6665
def get_rpaths_dev_tools(binary):
67-
command = (
68-
f"otool -l '{binary}' | grep -A2 LC_RPATH | grep path | "
69-
'grep "Xcode\\|CommandLineTools"'
70-
)
71-
result = subprocess.check_output(command, shell = True, universal_newlines=True)
72-
path_re = re.compile(r"^\s*path (.*) \(offset \d*\)$")
7366
return [
74-
match.group(1).strip()
75-
for line in result.splitlines()
76-
if (match := path_re.search(line)) is not None
67+
rpath for rpath in iter_rpaths(binary)
68+
if "Xcode" in rpath or "CommandLineTools" in rpath
7769
]
7870

7971
def resolve_lib_path(objfile, lib, rapths):
@@ -97,8 +89,7 @@ def resolve_lib_path(objfile, lib, rapths):
9789
def check_vulkan_max_version(version):
9890
try:
9991
subprocess.check_output(
100-
f"pkg-config vulkan --max-version={version}",
101-
shell=True,
92+
["pkg-config", "vulkan", f"--max-version={version}"],
10293
)
10394
return True
10495
except Exception:

0 commit comments

Comments
 (0)