Merge pull request #15571 from gerlero/relocate-relative-names
mac/keg_relocate: use relative install names
This commit is contained in:
commit
cff8d8c155
@ -45,20 +45,24 @@ class Keg
|
||||
change_dylib_id(dylib_id_for(file), file) if file.dylib?
|
||||
|
||||
each_linkage_for(file, :dynamically_linked_libraries) do |bad_name|
|
||||
# Don't fix absolute paths unless they are rooted in the build directory
|
||||
next if bad_name.start_with?("/") &&
|
||||
!rooted_in_build_directory?(bad_name)
|
||||
|
||||
new_name = fixed_name(file, bad_name)
|
||||
change_install_name(bad_name, new_name, file) if new_name != bad_name
|
||||
# Don't fix absolute paths unless they are rooted in the build directory.
|
||||
new_name = if bad_name.start_with?("/") && !rooted_in_build_directory?(bad_name)
|
||||
bad_name
|
||||
else
|
||||
fixed_name(file, bad_name)
|
||||
end
|
||||
loader_name = loader_name_for(file, new_name)
|
||||
change_install_name(bad_name, loader_name, file) if loader_name != bad_name
|
||||
end
|
||||
|
||||
each_linkage_for(file, :rpaths) do |bad_name|
|
||||
# Strip duplicate rpaths and rpaths rooted in the build directory.
|
||||
next if !rooted_in_build_directory?(bad_name) &&
|
||||
(file.rpaths.count(bad_name) == 1)
|
||||
|
||||
delete_rpath(bad_name, file)
|
||||
if rooted_in_build_directory?(bad_name) || (file.rpaths.count(bad_name) > 1)
|
||||
delete_rpath(bad_name, file)
|
||||
else
|
||||
loader_name = loader_name_for(file, bad_name)
|
||||
change_rpath(bad_name, loader_name, file) if loader_name != bad_name
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -66,6 +70,15 @@ class Keg
|
||||
generic_fix_dynamic_linkage
|
||||
end
|
||||
|
||||
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)}"
|
||||
else
|
||||
target
|
||||
end
|
||||
end
|
||||
|
||||
# If file is a dylib or bundle itself, look for the dylib named by
|
||||
# bad_name relative to the lib directory, so that we can skip the more
|
||||
# expensive recursive search if possible.
|
||||
@ -90,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
|
||||
|
@ -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
|
||||
|
||||
def display_reverse_output
|
||||
@ -72,6 +74,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
|
||||
|
||||
sig { params(test: T::Boolean, strict: T::Boolean).returns(T::Boolean) }
|
||||
@ -81,7 +84,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
|
||||
@ -176,9 +179,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
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user