From 8d34f99e5c715ccef4045425c65bd62df96153e2 Mon Sep 17 00:00:00 2001 From: Peter Xia Date: Tue, 4 Aug 2026 10:52:23 -0700 Subject: [PATCH] dylib_unhell: makes is_user_lib more robust So it no longer depends on library install path. Some users (like me) have custom homebrew prefix that the old way might cause libraries to be incorrectly skipped. --- TOOLS/dylib_unhell.py | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/TOOLS/dylib_unhell.py b/TOOLS/dylib_unhell.py index 778cc24faf41a..d059e8203da1c 100755 --- a/TOOLS/dylib_unhell.py +++ b/TOOLS/dylib_unhell.py @@ -11,28 +11,44 @@ usr_re = re.compile("^/usr/lib/") exe_re = re.compile("@executable_path") -def is_user_lib(objfile, libname): +def is_user_lib(libname): + base = os.path.basename(libname) return not sys_re.match(libname) and \ not usr_re.match(libname) and \ not exe_re.match(libname) and \ - "libobjc." not in libname and \ - "libSystem." not in libname and \ - "libc." not in libname and \ - "libgcc." not in libname and \ - os.path.basename(libname) != "Python" and \ - os.path.basename(objfile) not in libname and \ - "libswift" not in libname + "libobjc." not in base and \ + "libSystem." not in base and \ + "libc." not in base and \ + "libgcc." not in base and \ + base != "Python" and \ + "libswift" not in base + +def otool_self_id(objfile): + # dylibs list their own LC_ID_DYLIB as the first `otool -L` entry; + # executables have none. Matching it exactly (via `otool -D`) avoids + # excluding real dependencies whose path merely happens to contain the + # binary's basename. + output = subprocess.check_output( + ["otool", "-D", objfile], universal_newlines=True, + ) + lines = output.splitlines() + if len(lines) < 2: + return None + return lines[1].strip() def otool(objfile, rapths): output = subprocess.check_output( ["otool", "-L", objfile], universal_newlines=True, ) + self_id = otool_self_id(objfile) libs = set() for line in output.splitlines(): if not line.startswith("\t"): continue lib = line.split()[0] - if is_user_lib(objfile, lib): + if lib == self_id: + continue + if is_user_lib(lib): libs.add(lib) libs_resolved = set()