From dbeac5958462f1617c7270c9f5ac6c3ad324c1d9 Mon Sep 17 00:00:00 2001 From: Carlo Cabrera <30379873+carlocab@users.noreply.github.com> Date: Mon, 7 Aug 2023 14:43:56 +0800 Subject: [PATCH] keg_relocate: retain framework info in relocatable install names MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `dyld` uses the target library's install name to work out whether this is a Framework or a dylib, which affects how `dyld` searches for the desired library. We should therefore avoid confusing `dyld` by including the `*.framework` part of the install name in the target dylib, which is what this change does. Here's a concrete example of what this changes. Before: ❯ otool -L /usr/local/bin/python3 /usr/local/bin/python3: @loader_path/../Python (compatibility version 3.11.0, current version 3.11.0) /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1319.100.3) After: ❯ otool -L /usr/local/bin/python3 /usr/local/bin/python3: @loader_path/../../../../Python.framework/Versions/3.11/Python (compatibility version 3.11.0, current version 3.11.0) /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1319.100.3) By retaining the `Python.framework` part of the install name, we make sure that `dyld` knows that it should be looking for a framework rather than a dylib. --- Library/Homebrew/extend/os/mac/keg_relocate.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Library/Homebrew/extend/os/mac/keg_relocate.rb b/Library/Homebrew/extend/os/mac/keg_relocate.rb index 47ebe2e265..550ef5b667 100644 --- a/Library/Homebrew/extend/os/mac/keg_relocate.rb +++ b/Library/Homebrew/extend/os/mac/keg_relocate.rb @@ -80,7 +80,10 @@ class Keg def loader_name_for(file, target) # Use @loader_path-relative install names for other Homebrew-installed binaries. if ENV["HOMEBREW_RELOCATABLE_INSTALL_NAMES"] && target.start_with?(HOMEBREW_PREFIX) - "@loader_path/#{Pathname(target).relative_path_from(file.dirname)}" + dylib_suffix = find_dylib_suffix_from(target) + target_dir = Pathname.new(target.delete_suffix(dylib_suffix)).cleanpath + + "@loader_path/#{target_dir.relative_path_from(file.dirname)/dylib_suffix}" else target end