module MacOS extend self # This can be compared to numerics, strings, or symbols # using the standard Ruby Comparable methods. def version require 'version' MacOSVersion.new(MACOS_VERSION.to_s) end def cat if version == :mountain_lion then :mountainlion elsif version == :lion then :lion elsif version == :snow_leopard then :snowleopard elsif version == :leopard then :leopard else nil end end def locate tool # Don't call tools (cc, make, strip, etc.) directly! # Give the name of the binary you look for as a string to this method # in order to get the full path back as a Pathname. (@locate ||= {}).fetch(tool.to_s) do @locate[tool.to_s] = if File.executable? "/usr/bin/#{tool}" Pathname.new "/usr/bin/#{tool}" else # If the tool isn't in /usr/bin, then we first try to use xcrun to find # it. If it's not there, or xcode-select is misconfigured, we have to # look in dev_tools_path, and finally in xctoolchain_path, because the # tools were split over two locations beginning with Xcode 4.3+. xcrun_path = unless Xcode.bad_xcode_select_path? `/usr/bin/xcrun -find #{tool} 2>/dev/null`.chomp end paths = %W[#{xcrun_path} #{dev_tools_path}/#{tool} #{xctoolchain_path}/usr/bin/#{tool}] paths.map { |p| Pathname.new(p) }.find { |p| p.executable? } end end end def dev_tools_path @dev_tools_path ||= if File.exist? "/usr/bin/cc" and File.exist? "/usr/bin/make" # probably a safe enough assumption (the unix way) Pathname.new "/usr/bin" # Note that the exit status of system "xcrun foo" isn't always accurate elsif not Xcode.bad_xcode_select_path? and not `/usr/bin/xcrun -find make 2>/dev/null`.empty? # Wherever "make" is there are the dev tools. Pathname.new(`/usr/bin/xcrun -find make`.chomp).dirname elsif File.exist? "#{Xcode.prefix}/usr/bin/make" # cc stopped existing with Xcode 4.3, there are c89 and c99 options though Pathname.new "#{Xcode.prefix}/usr/bin" end end def xctoolchain_path # As of Xcode 4.3, some tools are located in the "xctoolchain" directory @xctoolchain_path ||= begin path = Pathname.new("#{Xcode.prefix}/Toolchains/XcodeDefault.xctoolchain") # If only the CLT are installed, all tools will be under dev_tools_path, # this path won't exist, and xctoolchain_path will be nil. path if path.exist? end end def sdk_path(v = version) (@sdk_path ||= {}).fetch(v.to_s) do @sdk_path[v.to_s] = begin opts = [] # First query Xcode itself opts << `#{locate('xcodebuild')} -version -sdk macosx#{v} Path 2>/dev/null`.chomp unless Xcode.bad_xcode_select_path? # Xcode.prefix is pretty smart, so lets look inside to find the sdk opts << "#{Xcode.prefix}/Platforms/MacOSX.platform/Developer/SDKs/MacOSX#{v}.sdk" # Xcode < 4.3 style opts << "/Developer/SDKs/MacOSX#{v}.sdk" opts.map{|a| Pathname.new(a) }.detect { |p| p.directory? } end end end def default_cc cc = locate 'cc' Pathname.new(cc).realpath.basename.to_s rescue nil end def default_compiler case default_cc when /^gcc/ then :gcc when /^llvm/ then :llvm when "clang" then :clang else # guess :( if Xcode.version >= "4.3" :clang elsif Xcode.version >= "4.2" :llvm else :gcc end end end def gcc_40_build_version @gcc_40_build_version ||= if locate("gcc-4.0") `#{locate("gcc-4.0")} --version` =~ /build (\d{4,})/ $1.to_i end end def gcc_42_build_version @gcc_42_build_version ||= if locate("gcc-4.2") \ and not locate("gcc-4.2").realpath.basename.to_s =~ /^llvm/ `#{locate("gcc-4.2")} --version` =~ /build (\d{4,})/ $1.to_i end end def llvm_build_version # for Xcode 3 on OS X 10.5 this will not exist # NOTE may not be true anymore but we can't test @llvm_build_version ||= if locate("llvm-gcc") `#{locate("llvm-gcc")} --version` =~ /LLVM build (\d{4,})/ $1.to_i end end def clang_version @clang_version ||= if locate("clang") `#{locate("clang")} --version` =~ /clang version (\d\.\d)/ $1 end end def clang_build_version @clang_build_version ||= if locate("clang") `#{locate("clang")} --version` =~ %r[tags/Apple/clang-(\d{2,})] $1.to_i end end # See these issues for some history: # http://github.com/mxcl/homebrew/issues/#issue/13 # http://github.com/mxcl/homebrew/issues/#issue/41 # http://github.com/mxcl/homebrew/issues/#issue/48 def macports_or_fink paths = [] # First look in the path because MacPorts is relocatable and Fink # may become relocatable in the future. %w{port fink}.each do |ponk| path = which(ponk) paths << path unless path.nil? end # Look in the standard locations, because even if port or fink are # not in the path they can still break builds if the build scripts # have these paths baked in. %w{/sw/bin/fink /opt/local/bin/port}.each do |ponk| path = Pathname.new(ponk) paths << path if path.exist? end # Finally, some users make their MacPorts or Fink directorie # read-only in order to try out Homebrew, but this doens't work as # some build scripts error out when trying to read from these now # unreadable paths. %w{/sw /opt/local}.map { |p| Pathname.new(p) }.each do |path| paths << path if path.exist? && !path.readable? end paths.uniq end def prefer_64_bit? Hardware.is_64_bit? and version != :leopard end STANDARD_COMPILERS = { "3.1.4" => { :gcc_40_build => 5493, :gcc_42_build => 5577 }, "3.2.6" => { :gcc_40_build => 5494, :gcc_42_build => 5666, :llvm_build => 2335, :clang => "1.7", :clang_build => 77 }, "4.0" => { :gcc_40_build => 5494, :gcc_42_build => 5666, :llvm_build => 2335, :clang => "2.0", :clang_build => 137 }, "4.0.1" => { :gcc_40_build => 5494, :gcc_42_build => 5666, :llvm_build => 2335, :clang => "2.0", :clang_build => 137 }, "4.0.2" => { :gcc_40_build => 5494, :gcc_42_build => 5666, :llvm_build => 2335, :clang => "2.0", :clang_build => 137 }, "4.2" => { :llvm_build => 2336, :clang => "3.0", :clang_build => 211 }, "4.3" => { :llvm_build => 2336, :clang => "3.1", :clang_build => 318 }, "4.3.1" => { :llvm_build => 2336, :clang => "3.1", :clang_build => 318 }, "4.3.2" => { :llvm_build => 2336, :clang => "3.1", :clang_build => 318 }, "4.3.3" => { :llvm_build => 2336, :clang => "3.1", :clang_build => 318 }, "4.4" => { :llvm_build => 2336, :clang => "4.0", :clang_build => 421 }, "4.4.1" => { :llvm_build => 2336, :clang => "4.0", :clang_build => 421 }, "4.5" => { :llvm_build => 2336, :clang => "4.1", :clang_build => 421 }, "4.5.1" => { :llvm_build => 2336, :clang => "4.1", :clang_build => 421 }, "4.5.2" => { :llvm_build => 2336, :clang => "4.1", :clang_build => 421 } } def compilers_standard? xcode = Xcode.version unless STANDARD_COMPILERS.keys.include? xcode onoe <<-EOS.undent Homebrew doesn't know what compiler versions ship with your version of Xcode. Please `brew update` and if that doesn't help, file an issue with the output of `brew --config`: https://github.com/mxcl/homebrew/issues Thanks! EOS return end STANDARD_COMPILERS[xcode].all? do |method, build| MacOS.send(:"#{method}_version") == build end end def app_with_bundle_id id path = mdfind(id).first Pathname.new(path) unless path.nil? or path.empty? end def mdfind id `/usr/bin/mdfind "kMDItemCFBundleIdentifier == '#{id}'"`.split("\n") end def pkgutil_info id `/usr/sbin/pkgutil --pkg-info "#{id}" 2>/dev/null`.strip end def bottles_supported? raise_if_failed=false # We support bottles on all versions of OS X except 32-bit Snow Leopard. if Hardware.is_32_bit? and MacOS.version == :snow_leopard return false unless raise_if_failed raise "Bottles are not supported on 32-bit Snow Leopard." end unless HOMEBREW_PREFIX.to_s == '/usr/local' return false unless raise_if_failed raise "Bottles are only supported with a /usr/local prefix." end unless HOMEBREW_CELLAR.to_s == '/usr/local/Cellar' return false unless raise_if_failed raise "Bottles are only supported with a /usr/local/Cellar cellar." end true end end require 'macos/xcode' require 'macos/xquartz'