From acae97e70fe0c6c3354960e2e89a1157d06cfdaa Mon Sep 17 00:00:00 2001 From: Carlo Cabrera <30379873+carlocab@users.noreply.github.com> Date: Thu, 27 Jul 2023 11:53:46 +0800 Subject: [PATCH 1/2] os/mac/mach: resolve rpaths too MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We can add a small amount of logic to `#resolve_variable_name` that will allow us to perform (limited) resolution of rpath references. This is for informational purposes only: failing to resolve an `@rpath` reference will not (and should not) result in `brew linkage` failures. `dyld` will typically have more information than we do to resolve these references, so not failing `brew linkage` when we fail to resolve an `@rpath` reference is the right behaviour here. As an example, before: ❯ brew linkage jpeg-turbo System libraries: /usr/lib/libSystem.B.dylib @rpath-referenced libraries: @rpath/libjpeg.8.dylib @rpath/libturbojpeg.0.dylib After: ❯ brew linkage jpeg-turbo System libraries: /usr/lib/libSystem.B.dylib Homebrew libraries: /usr/local/Cellar/jpeg-turbo/3.0.0/lib/libjpeg.8.dylib (jpeg-turbo) /usr/local/Cellar/jpeg-turbo/3.0.0/lib/libturbojpeg.0.dylib (jpeg-turbo) --- Library/Homebrew/os/mac/mach.rb | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Library/Homebrew/os/mac/mach.rb b/Library/Homebrew/os/mac/mach.rb index f9818d6f84..38f52dc4c9 100644 --- a/Library/Homebrew/os/mac/mach.rb +++ b/Library/Homebrew/os/mac/mach.rb @@ -110,11 +110,22 @@ module MachOShim Pathname(name.sub("@loader_path", dirname)).cleanpath.to_s elsif name.start_with?("@executable_path") && binary_executable? Pathname(name.sub("@executable_path", dirname)).cleanpath.to_s + elsif name.start_with?("@rpath") && (target = resolve_rpath(name)).present? + target else name end end + def resolve_rpath(name) + target = T.let(nil, T.nilable(String)) + return unless rpaths(resolve_variable_references: true).find do |rpath| + File.exist?(target = File.join(rpath, name.delete_prefix("@rpath"))) + end + + target + end + def archs mach_data.map { |m| m.fetch :arch } end From b80940e1d8540eb2af009f2f805b4f2055a23c5f Mon Sep 17 00:00:00 2001 From: Carlo Cabrera <30379873+carlocab@users.noreply.github.com> Date: Thu, 27 Jul 2023 12:00:10 +0800 Subject: [PATCH 2/2] os/mac/mach: simplify We can avoid having to define a local variable and then reference it inside these blocks by passing a proc instead. --- Library/Homebrew/os/mac/mach.rb | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/Library/Homebrew/os/mac/mach.rb b/Library/Homebrew/os/mac/mach.rb index 38f52dc4c9..bbd8e7c01e 100644 --- a/Library/Homebrew/os/mac/mach.rb +++ b/Library/Homebrew/os/mac/mach.rb @@ -89,18 +89,15 @@ module MachOShim def dynamically_linked_libraries(except: :none, resolve_variable_references: true) lcs = macho.dylib_load_commands.reject { |lc| lc.type == except } - names = lcs.map(&:name).map(&:to_s).uniq - - names.map! { |name| resolve_variable_name(name) } if resolve_variable_references + names.map!(&method(:resolve_variable_name)) if resolve_variable_references names end def rpaths(resolve_variable_references: true) names = macho.rpaths - - names.map! { |name| resolve_variable_name(name) } if resolve_variable_references + names.map!(&method(:resolve_variable_name)) if resolve_variable_references names end