diff --git a/Library/Homebrew/keg_relocate.rb b/Library/Homebrew/keg_relocate.rb index 28eb5ef0f4..8c8a0d867d 100644 --- a/Library/Homebrew/keg_relocate.rb +++ b/Library/Homebrew/keg_relocate.rb @@ -70,16 +70,6 @@ class Keg end end - def change_dylib_id(id, file) - puts "Changing dylib ID of #{file}\n from #{file.dylib_id}\n to #{id}" if ARGV.debug? - install_name_tool("-id", id, file) - end - - def change_install_name(old, new, file) - puts "Changing install name in #{file}\n from #{old}\n to #{new}" if ARGV.debug? - install_name_tool("-change", old, new, file) - end - # Detects the C++ dynamic libraries in place, scanning the dynamic links # of the files within the keg. # Note that this doesn't attempt to distinguish between libstdc++ versions, @@ -110,16 +100,6 @@ class Keg end end - def install_name_tool(*args) - @require_install_name_tool = true - tool = MacOS.install_name_tool - system(tool, *args) || raise(ErrorDuringExecution.new(tool, args)) - end - - def require_install_name_tool? - !!@require_install_name_tool - 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. diff --git a/Library/Homebrew/os/mac.rb b/Library/Homebrew/os/mac.rb index e5ddb65021..cdf528e39e 100644 --- a/Library/Homebrew/os/mac.rb +++ b/Library/Homebrew/os/mac.rb @@ -4,6 +4,7 @@ require "os/mac/xcode" require "os/mac/xquartz" require "os/mac/pathname" require "os/mac/sdk" +require "os/mac/keg" module OS module Mac diff --git a/Library/Homebrew/os/mac/cctools_keg.rb b/Library/Homebrew/os/mac/cctools_keg.rb new file mode 100644 index 0000000000..cd928f5227 --- /dev/null +++ b/Library/Homebrew/os/mac/cctools_keg.rb @@ -0,0 +1,21 @@ +module CctoolsKeg + def install_name_tool(*args) + @require_install_name_tool = true + tool = MacOS.install_name_tool + system(tool, *args) || raise(ErrorDuringExecution.new(tool, args)) + end + + def require_install_name_tool? + !!@require_install_name_tool + end + + def change_dylib_id(id, file) + puts "Changing dylib ID of #{file}\n from #{file.dylib_id}\n to #{id}" if ARGV.debug? + install_name_tool("-id", id, file) + end + + def change_install_name(old, new, file) + puts "Changing install name in #{file}\n from #{old}\n to #{new}" if ARGV.debug? + install_name_tool("-change", old, new, file) + end +end diff --git a/Library/Homebrew/os/mac/hardware.rb b/Library/Homebrew/os/mac/hardware.rb index df1f7fab6d..84308b67e6 100644 --- a/Library/Homebrew/os/mac/hardware.rb +++ b/Library/Homebrew/os/mac/hardware.rb @@ -1,4 +1,4 @@ -require "os/mac/mach" +require "os/mac/pathname" module MacCPUs OPTIMIZATION_FLAGS = { diff --git a/Library/Homebrew/os/mac/keg.rb b/Library/Homebrew/os/mac/keg.rb new file mode 100644 index 0000000000..dcda0908b7 --- /dev/null +++ b/Library/Homebrew/os/mac/keg.rb @@ -0,0 +1,9 @@ +class Keg + if ENV["HOMEBREW_RUBY_MACHO"] + require "os/mac/ruby_keg" + include RubyKeg + else + require "os/mac/cctools_keg" + include CctoolsKeg + end +end diff --git a/Library/Homebrew/os/mac/pathname.rb b/Library/Homebrew/os/mac/pathname.rb index 9b65d7ac02..fbe4ad5ec7 100644 --- a/Library/Homebrew/os/mac/pathname.rb +++ b/Library/Homebrew/os/mac/pathname.rb @@ -1,5 +1,9 @@ -require "os/mac/mach" - class Pathname - include MachO + if ENV["HOMEBREW_RUBY_MACHO"] + require "os/mac/ruby_mach" + include RubyMachO + else + require "os/mac/cctools_mach" + include CctoolsMachO + end end diff --git a/Library/Homebrew/os/mac/ruby_keg.rb b/Library/Homebrew/os/mac/ruby_keg.rb new file mode 100644 index 0000000000..f6fc334952 --- /dev/null +++ b/Library/Homebrew/os/mac/ruby_keg.rb @@ -0,0 +1,19 @@ +require "vendor/macho/macho" + +module RubyKeg + def change_dylib_id(id, file) + @require_install_name_tool = true + puts "Changing dylib ID of #{file}\n from #{file.dylib_id}\n to #{id}" if ARGV.debug? + MachO::Tools.change_dylib_id(file, id) + end + + def change_install_name(old, new, file) + @require_install_name_tool = true + puts "Changing install name in #{file}\n from #{old}\n to #{new}" if ARGV.debug? + MachO::Tools.change_install_name(file, old, new) + end + + def require_install_name_tool? + !!@require_install_name_tool + end +end diff --git a/Library/Homebrew/os/mac/ruby_mach.rb b/Library/Homebrew/os/mac/ruby_mach.rb new file mode 100644 index 0000000000..3cd0ac0b9d --- /dev/null +++ b/Library/Homebrew/os/mac/ruby_mach.rb @@ -0,0 +1,103 @@ +require "vendor/macho/macho" +require "os/mac/architecture_list" + +module RubyMachO + # @private + def macho + @macho ||= begin + MachO.open(to_s) + end + end + + # @private + def mach_data + @mach_data ||= begin + machos = [] + mach_data = [] + + if MachO.fat_magic?(macho.magic) + machos = macho.machos + else + machos << macho + end + + machos.each do |m| + arch = case m.cputype + when "CPU_TYPE_I386" then :i386 + when "CPU_TYPE_X86_64" then :x86_64 + when "CPU_TYPE_POWERPC" then :ppc7400 + when "CPU_TYPE_POWERPC64" then :ppc64 + else :dunno + end + + type = case m.filetype + when "MH_EXECUTE" then :executable + when "MH_DYLIB" then :dylib + when "MH_BUNDLE" then :bundle + else :dunno + end + + mach_data << { :arch => arch, :type => type } + end + + mach_data + rescue + [] + end + end + + def archs + mach_data.map { |m| m.fetch :arch }.extend(ArchitectureListExtension) + end + + def arch + case archs.length + when 0 then :dunno + when 1 then archs.first + else :universal + end + end + + def universal? + arch == :universal + end + + def i386? + arch == :i386 + end + + def x86_64? + arch == :x86_64 + end + + def ppc7400? + arch == :ppc7400 + end + + def ppc64? + arch == :ppc64 + end + + # @private + def dylib? + mach_data.any? { |m| m.fetch(:type) == :dylib } + end + + # @private + def mach_o_executable? + mach_data.any? { |m| m.fetch(:type) == :executable } + end + + # @private + def mach_o_bundle? + mach_data.any? { |m| m.fetch(:type) == :bundle } + end + + def dynamically_linked_libraries + macho.linked_dylibs + end + + def dylib_id + macho.dylib_id + end +end