aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJack Nagel2012-06-16 16:14:47 -0500
committerJack Nagel2012-06-17 16:22:08 -0500
commitd33b6815e7ebe8a0ddda65f9fd5bde2022a6e70a (patch)
treee5b5f86e2e2183697d8faad0d68c02f990902170
parent92d373aad57c23f134a1c8dc7c267a76aa726658 (diff)
downloadhomebrew-d33b6815e7ebe8a0ddda65f9fd5bde2022a6e70a.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 #12810. Signed-off-by: Jack Nagel <jacknagel@gmail.com>
-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