From 15a0c7fd7df2cae55e3b702a04e7bbf1ad401f27 Mon Sep 17 00:00:00 2001 From: Gabriel Gerlero Date: Tue, 20 Jun 2023 16:42:13 -0300 Subject: [PATCH] linkage_checker: resolve some variable install names on macOS --- .../Homebrew/extend/os/mac/keg_relocate.rb | 2 +- Library/Homebrew/linkage_checker.rb | 12 ++++++-- Library/Homebrew/os/mac/mach.rb | 28 +++++++++++++++++-- 3 files changed, 35 insertions(+), 7 deletions(-) diff --git a/Library/Homebrew/extend/os/mac/keg_relocate.rb b/Library/Homebrew/extend/os/mac/keg_relocate.rb index 83888fb51d..c36e0ffb7e 100644 --- a/Library/Homebrew/extend/os/mac/keg_relocate.rb +++ b/Library/Homebrew/extend/os/mac/keg_relocate.rb @@ -103,7 +103,7 @@ class Keg def each_linkage_for(file, linkage_type, &block) links = file.method(linkage_type) - .call + .call(resolve_variable_references: false) .grep_v(/^@(loader_|executable_|r)path/) links.each(&block) end diff --git a/Library/Homebrew/linkage_checker.rb b/Library/Homebrew/linkage_checker.rb index 17c4542b3c..d7646826f3 100644 --- a/Library/Homebrew/linkage_checker.rb +++ b/Library/Homebrew/linkage_checker.rb @@ -31,6 +31,7 @@ class LinkageChecker @unwanted_system_dylibs = [] @version_conflict_deps = [] @files_missing_rpaths = [] + @executable_path_dylibs = [] check_dylibs(rebuild_cache: rebuild_cache) end @@ -39,13 +40,14 @@ class LinkageChecker display_items "System libraries", @system_dylibs display_items "Homebrew libraries", @brewed_dylibs display_items "Indirect dependencies with linkage", @indirect_deps - display_items "Variable-referenced libraries", @variable_dylibs + display_items "@rpath-referenced libraries", @variable_dylibs display_items "Missing libraries", @broken_dylibs display_items "Broken dependencies", @broken_deps display_items "Undeclared dependencies with linkage", @undeclared_deps display_items "Dependencies with no linkage", @unnecessary_deps display_items "Unwanted system libraries", @unwanted_system_dylibs display_items "Files with missing rpath", @files_missing_rpaths + display_items "@executable_path references in libraries", @executable_path_dylibs end alias generic_display_normal_output display_normal_output private :generic_display_normal_output @@ -74,6 +76,7 @@ class LinkageChecker display_items "Undeclared dependencies with linkage", @undeclared_deps, puts_output: puts_output display_items "Files with missing rpath", @files_missing_rpaths, puts_output: puts_output + display_items "@executable_path references in libraries", @executable_path_dylibs, puts_output: puts_output end alias generic_display_test_output display_test_output private :generic_display_test_output @@ -85,7 +88,7 @@ class LinkageChecker issues = [@broken_deps, unexpected_broken_dylibs] if test issues += [@unwanted_system_dylibs, @version_conflict_deps, unexpected_present_dylibs] - issues += [@undeclared_deps, @files_missing_rpaths] if strict + issues += [@undeclared_deps, @files_missing_rpaths, @executable_path_dylibs] if strict end issues.any?(&:present?) end @@ -182,9 +185,12 @@ class LinkageChecker checked_dylibs << dylib - if dylib.start_with? "@" + if dylib.start_with? "@rpath" @variable_dylibs << dylib next + elsif dylib.start_with?("@executable_path") && !Pathname(file).binary_executable? + @executable_path_dylibs << dylib + next end begin diff --git a/Library/Homebrew/os/mac/mach.rb b/Library/Homebrew/os/mac/mach.rb index b421103de7..300b61ab47 100644 --- a/Library/Homebrew/os/mac/mach.rb +++ b/Library/Homebrew/os/mac/mach.rb @@ -9,7 +9,7 @@ require "macho" module MachOShim extend Forwardable - delegate [:dylib_id, :rpaths] => :macho + delegate [:dylib_id] => :macho def macho @macho ||= MachO.open(to_s) @@ -79,10 +79,32 @@ module MachOShim macho.write! end - def dynamically_linked_libraries(except: :none) + def dynamically_linked_libraries(except: :none, resolve_variable_references: true) lcs = macho.dylib_load_commands.reject { |lc| lc.type == except } - lcs.map(&:name).map(&:to_s).uniq + names = lcs.map(&:name).map(&:to_s).uniq + + names.map! { |name| resolve_variable_name(name) } if resolve_variable_references + + names + end + + def rpaths(resolve_variable_references: true) + names = macho.rpaths.uniq + + names.map! { |name| resolve_variable_name(name) } if resolve_variable_references + + names + end + + def resolve_variable_name(name) + if name.start_with? "@loader_path" + 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 + else + name + end end def archs