aboutsummaryrefslogtreecommitdiffstats
path: root/Library/Homebrew
diff options
context:
space:
mode:
authorJack Nagel2012-06-16 16:14:47 -0500
committerJack Nagel2012-06-17 16:22:08 -0500
commit58d4a95ea71eef583ad1ceb938113ff7773b437e (patch)
tree4bf71762e3e7de9ac6375b6c0c4b9b142151a365 /Library/Homebrew
parent6229a20db7a8345b61b4a86484e55825f6ff5e86 (diff)
downloadbrew-58d4a95ea71eef583ad1ceb938113ff7773b437e.tar.bz2
fix_install_names: try harder to find referenced dylibs
Keg#fix_install_names punts if bad install names reference dylibs that aren't "nearby". Enable this machinery to fix more complex directory hierarchies by searching everything under 'lib' for the bad name's basename. Additionally, teach it to correctly handle Mach-O bundle files. Fixes Homebrew/homebrew#12810. Signed-off-by: Jack Nagel <jacknagel@gmail.com>
Diffstat (limited to 'Library/Homebrew')
-rw-r--r--Library/Homebrew/keg_fix_install_names.rb69
1 files changed, 42 insertions, 27 deletions
diff --git a/Library/Homebrew/keg_fix_install_names.rb b/Library/Homebrew/keg_fix_install_names.rb
index a4385d752..e2582c688 100644
--- a/Library/Homebrew/keg_fix_install_names.rb
+++ b/Library/Homebrew/keg_fix_install_names.rb
@@ -1,21 +1,31 @@
+require 'find'
+
class Keg
def fix_install_names
- dylibs.each do |dylib|
- bad_install_names_for dylib do |id, bad_names|
- dylib.ensure_writable do
- system "install_name_tool", "-id", id, dylib
+ mach_o_files.each do |file|
+ bad_install_names_for file do |id, bad_names|
+ file.ensure_writable do
+ system "install_name_tool", "-id", id, file if file.dylib?
+
bad_names.each do |bad_name|
new_name = bad_name
- new_name = Pathname.new(bad_name).basename unless (dylib.parent + new_name).exist?
- # this fixes some problems, maybe not all. opencv seems to have badnames of the type
- # "lib/libblah.dylib"
- if (dylib.parent + new_name).exist?
- system "install_name_tool", "-change", bad_name, "@loader_path/#{new_name}", dylib
+ new_name = Pathname.new(bad_name).basename unless (file.parent + new_name).exist?
+
+ # First check to see if the dylib is present in the current
+ # directory, so we can skip the more expensive search.
+ if (file.parent + new_name).exist?
+ system "install_name_tool", "-change", bad_name, "@loader_path/#{new_name}", file
else
- opoo "Could not fix install names for #{dylib}"
- if ARGV.debug?
- puts "bad_name: #{bad_name}"
- puts "new_name: #{new_name}"
+ # Otherwise, try and locate the appropriate dylib by walking
+ # the entire 'lib' tree recursively.
+ abs_name = (self+'lib').find do |pn|
+ break pn if pn.basename == Pathname.new(new_name)
+ end
+
+ if abs_name and abs_name.exist?
+ system "install_name_tool", "-change", bad_name, abs_name, file
+ else
+ opoo "Could not fix install names for #{file}"
end
end
end
@@ -28,35 +38,40 @@ class Keg
OTOOL_RX = /\t(.*) \(compatibility version (\d+\.)*\d+, current version (\d+\.)*\d+\)/
- def bad_install_names_for dylib
- dylib = dylib.to_s
-
- ENV['HOMEBREW_DYLIB'] = dylib # solves all shell escaping problems
- install_names = `otool -L "$HOMEBREW_DYLIB"`.split "\n"
+ def bad_install_names_for file
+ ENV['HOMEBREW_MACH_O_FILE'] = file.to_s # solves all shell escaping problems
+ install_names = `otool -L "$HOMEBREW_MACH_O_FILE"`.split "\n"
install_names.shift # first line is fluff
install_names.map!{ |s| OTOOL_RX =~ s && $1 }
- id = install_names.shift
+
+ # Bundles don't have an ID
+ id = install_names.shift unless file.mach_o_bundle?
+
install_names.compact!
install_names.reject!{ |fn| fn =~ /^@(loader|executable)_path/ }
- install_names.reject!{ |fn| fn[0,1] == '/' }
+
+ # Don't fix absolute paths unless they are rooted in the build directory
+ install_names.reject! do |fn|
+ tmp = ENV['HOMEBREW_TEMP'] ? Regexp.escape(ENV['HOMEBREW_TEMP']) : '/tmp'
+ fn[0,1] == '/' and not %r[^#{tmp}] === fn
+ end
# the shortpath ensures that library upgrades don’t break installed tools
- shortpath = HOMEBREW_PREFIX + Pathname.new(dylib).relative_path_from(self)
- id = if shortpath.exist? then shortpath else dylib end
+ shortpath = HOMEBREW_PREFIX + Pathname.new(file).relative_path_from(self)
+ id = if shortpath.exist? then shortpath else file end
yield id, install_names
end
- def dylibs
- require 'find'
- dylibs = []
+ def mach_o_files
+ mach_o_files = []
if (lib = join 'lib').directory?
lib.find do |pn|
next if pn.symlink? or pn.directory?
- dylibs << pn if pn.dylib?
+ mach_o_files << pn if pn.dylib? or pn.mach_o_bundle?
end
end
- dylibs
+ mach_o_files
end
end