2013-03-10 17:33:06 +00:00
|
|
|
require 'os/mac/version'
|
2013-06-01 16:27:53 -05:00
|
|
|
require 'hardware'
|
2013-02-06 22:49:43 -06:00
|
|
|
|
2012-06-27 12:09:57 -07:00
|
|
|
module MacOS extend self
|
2012-06-28 12:49:54 -05:00
|
|
|
|
2012-09-04 23:04:01 -05:00
|
|
|
# This can be compared to numerics, strings, or symbols
|
|
|
|
# using the standard Ruby Comparable methods.
|
2012-06-27 12:09:57 -07:00
|
|
|
def version
|
2013-04-15 15:59:19 -05:00
|
|
|
@version ||= Version.new(MACOS_VERSION)
|
2012-06-27 12:09:57 -07:00
|
|
|
end
|
|
|
|
|
|
|
|
def cat
|
2013-06-15 19:40:42 -05:00
|
|
|
version.to_sym
|
2013-06-06 16:02:27 -05:00
|
|
|
end
|
|
|
|
|
2012-06-27 12:09:57 -07:00
|
|
|
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.
|
2013-01-08 10:15:57 -06:00
|
|
|
(@locate ||= {}).fetch(tool.to_s) do
|
2013-07-26 23:21:44 -07:00
|
|
|
@locate[tool.to_s] = if File.executable?(path = "/usr/bin/#{tool}")
|
|
|
|
Pathname.new path
|
|
|
|
# Homebrew GCCs most frequently; much faster to check this before xcrun
|
|
|
|
# This also needs to be queried if xcrun won't work, e.g. CLT-only
|
|
|
|
elsif File.executable?(path = "#{HOMEBREW_PREFIX}/bin/#{tool}")
|
|
|
|
Pathname.new path
|
2013-01-08 10:15:57 -06:00
|
|
|
else
|
2013-07-26 23:21:44 -07:00
|
|
|
# If the tool isn't in /usr/bin or from Homebrew,
|
|
|
|
# then we first try to use xcrun to find it.
|
|
|
|
# If it's not there, or xcode-select is misconfigured, we have to
|
2013-01-08 10:15:57 -06:00
|
|
|
# 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?
|
2013-02-01 13:36:53 -06:00
|
|
|
path = `/usr/bin/xcrun -find #{tool} 2>/dev/null`.chomp
|
|
|
|
# If xcrun finds a superenv tool then discard the result.
|
2013-02-28 20:50:08 +00:00
|
|
|
path unless path.include?("Library/ENV")
|
2013-01-08 10:15:57 -06:00
|
|
|
end
|
2012-08-17 23:22:34 -05:00
|
|
|
|
2013-01-08 10:15:57 -06:00
|
|
|
paths = %W[#{xcrun_path}
|
|
|
|
#{dev_tools_path}/#{tool}
|
|
|
|
#{xctoolchain_path}/usr/bin/#{tool}]
|
|
|
|
paths.map { |p| Pathname.new(p) }.find { |p| p.executable? }
|
|
|
|
end
|
2012-06-27 12:09:57 -07:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def dev_tools_path
|
2013-07-21 16:41:50 -05:00
|
|
|
@dev_tools_path ||= if tools_in_prefix? CLT::STANDALONE_PKG_PATH
|
2013-06-25 16:49:08 +01:00
|
|
|
# In 10.9 the CLT moved from /usr into /Library/Developer/CommandLineTools.
|
2013-07-21 16:41:50 -05:00
|
|
|
Pathname.new "#{CLT::STANDALONE_PKG_PATH}/usr/bin"
|
|
|
|
elsif tools_in_prefix? "/"
|
2012-06-27 12:09:57 -07:00
|
|
|
# probably a safe enough assumption (the unix way)
|
|
|
|
Pathname.new "/usr/bin"
|
2012-08-09 16:33:41 -05:00
|
|
|
elsif not Xcode.bad_xcode_select_path? and not `/usr/bin/xcrun -find make 2>/dev/null`.empty?
|
2013-07-21 16:41:50 -05:00
|
|
|
# Note that the exit status of system "xcrun foo" isn't always accurate
|
2012-06-27 12:09:57 -07:00
|
|
|
# Wherever "make" is there are the dev tools.
|
|
|
|
Pathname.new(`/usr/bin/xcrun -find make`.chomp).dirname
|
2012-07-09 14:58:34 -05:00
|
|
|
elsif File.exist? "#{Xcode.prefix}/usr/bin/make"
|
2012-06-27 12:09:57 -07:00
|
|
|
# cc stopped existing with Xcode 4.3, there are c89 and c99 options though
|
2012-07-09 14:58:34 -05:00
|
|
|
Pathname.new "#{Xcode.prefix}/usr/bin"
|
2012-06-27 12:09:57 -07:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2013-07-21 16:41:50 -05:00
|
|
|
def tools_in_prefix?(prefix)
|
2013-07-21 16:41:51 -05:00
|
|
|
%w{cc make}.all? { |tool| File.executable? "#{prefix}/usr/bin/#{tool}" }
|
2013-07-21 16:41:50 -05:00
|
|
|
end
|
|
|
|
|
2012-06-27 12:09:57 -07:00
|
|
|
def xctoolchain_path
|
2012-06-30 14:01:07 -05:00
|
|
|
# As of Xcode 4.3, some tools are located in the "xctoolchain" directory
|
2012-06-27 12:09:57 -07:00
|
|
|
@xctoolchain_path ||= begin
|
2012-07-09 14:58:34 -05:00
|
|
|
path = Pathname.new("#{Xcode.prefix}/Toolchains/XcodeDefault.xctoolchain")
|
2012-06-30 14:01:07 -05:00
|
|
|
# If only the CLT are installed, all tools will be under dev_tools_path,
|
2012-06-30 14:10:03 -05:00
|
|
|
# this path won't exist, and xctoolchain_path will be nil.
|
2012-06-30 14:01:07 -05:00
|
|
|
path if path.exist?
|
2012-06-27 12:09:57 -07:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2012-08-31 09:51:08 -04:00
|
|
|
def sdk_path(v = version)
|
2013-01-08 10:15:57 -06:00
|
|
|
(@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
|
2012-06-27 12:09:57 -07:00
|
|
|
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 :(
|
2012-07-09 14:58:34 -05:00
|
|
|
if Xcode.version >= "4.3"
|
2012-06-27 12:09:57 -07:00
|
|
|
:clang
|
2012-07-09 14:58:34 -05:00
|
|
|
elsif Xcode.version >= "4.2"
|
2012-06-27 12:09:57 -07:00
|
|
|
:llvm
|
|
|
|
else
|
|
|
|
:gcc
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2012-06-28 12:50:10 -05:00
|
|
|
def gcc_40_build_version
|
2013-07-20 22:40:23 -05:00
|
|
|
@gcc_40_build_version ||=
|
|
|
|
if (path = locate("gcc-4.0"))
|
2013-07-21 07:56:30 -05:00
|
|
|
%x{#{path} --version}[/build (\d{4,})/, 1].to_i
|
2013-07-20 22:40:23 -05:00
|
|
|
end
|
2012-06-28 12:50:10 -05:00
|
|
|
end
|
2013-04-13 01:07:46 -05:00
|
|
|
alias_method :gcc_4_0_build_version, :gcc_40_build_version
|
2012-06-28 12:50:10 -05:00
|
|
|
|
|
|
|
def gcc_42_build_version
|
2013-07-20 22:40:23 -05:00
|
|
|
@gcc_42_build_version ||=
|
|
|
|
if (path = locate("gcc-4.2")) && path.realpath.basename.to_s !~ /^llvm/
|
|
|
|
%x{#{path} --version}[/build (\d{4,})/, 1].to_i
|
|
|
|
end
|
2012-06-28 12:50:10 -05:00
|
|
|
end
|
2013-04-01 13:23:09 -05:00
|
|
|
alias_method :gcc_build_version, :gcc_42_build_version
|
2012-06-28 12:50:10 -05:00
|
|
|
|
2012-06-27 12:09:57 -07:00
|
|
|
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
|
2013-07-20 22:40:22 -05:00
|
|
|
@llvm_build_version ||=
|
|
|
|
if (path = locate("llvm-gcc")) && path.realpath.basename.to_s !~ /^clang/
|
|
|
|
%x{#{path} --version}[/LLVM build (\d{4,})/, 1].to_i
|
|
|
|
end
|
2012-06-27 12:09:57 -07:00
|
|
|
end
|
|
|
|
|
|
|
|
def clang_version
|
2013-07-20 22:40:23 -05:00
|
|
|
@clang_version ||=
|
|
|
|
if (path = locate("clang"))
|
|
|
|
%x{#{path} --version}[/(?:clang|LLVM) version (\d\.\d)/, 1]
|
|
|
|
end
|
2012-06-27 12:09:57 -07:00
|
|
|
end
|
|
|
|
|
|
|
|
def clang_build_version
|
2013-07-20 22:40:23 -05:00
|
|
|
@clang_build_version ||=
|
|
|
|
if (path = locate("clang"))
|
2013-07-21 07:56:30 -05:00
|
|
|
%x{#{path} --version}[%r[clang-(\d{2,})], 1].to_i
|
2013-07-20 22:40:23 -05:00
|
|
|
end
|
2012-06-27 12:09:57 -07:00
|
|
|
end
|
|
|
|
|
2013-06-28 01:38:09 -05:00
|
|
|
def non_apple_gcc_version(cc)
|
|
|
|
return unless path = locate(cc)
|
|
|
|
|
|
|
|
ivar = "@#{cc.gsub(/(-|\.)/, '')}_version"
|
|
|
|
return instance_variable_get(ivar) if instance_variable_defined?(ivar)
|
|
|
|
|
|
|
|
`#{path} --version` =~ /gcc-\d.\d \(GCC\) (\d\.\d\.\d)/
|
|
|
|
instance_variable_set(ivar, $1)
|
|
|
|
end
|
|
|
|
|
2012-12-17 17:05:53 -06:00
|
|
|
# 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|
|
2012-06-27 12:09:57 -07:00
|
|
|
path = which(ponk)
|
2012-12-17 17:05:53 -06:00
|
|
|
paths << path unless path.nil?
|
2012-06-27 12:09:57 -07:00
|
|
|
end
|
|
|
|
|
2012-12-17 17:05:53 -06:00
|
|
|
# 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?
|
2012-06-27 12:09:57 -07:00
|
|
|
end
|
|
|
|
|
2012-12-17 17:05:53 -06:00
|
|
|
# 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?
|
2012-06-27 12:09:57 -07:00
|
|
|
end
|
|
|
|
|
2012-12-17 17:05:53 -06:00
|
|
|
paths.uniq
|
2012-06-27 12:09:57 -07:00
|
|
|
end
|
|
|
|
|
|
|
|
def prefer_64_bit?
|
2013-06-13 12:04:58 -05:00
|
|
|
Hardware::CPU.is_64_bit? and version != :leopard
|
2012-06-27 12:09:57 -07:00
|
|
|
end
|
|
|
|
|
2013-08-01 19:46:56 -07:00
|
|
|
def preferred_arch
|
|
|
|
@preferred_arch ||= if prefer_64_bit?
|
|
|
|
Hardware::CPU.arch_64_bit
|
|
|
|
else
|
|
|
|
Hardware::CPU.arch_32_bit
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2012-10-15 18:16:18 -05:00
|
|
|
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 },
|
2012-11-01 14:13:26 -05:00
|
|
|
"4.5.1" => { :llvm_build => 2336, :clang => "4.1", :clang_build => 421 },
|
2013-01-28 12:12:15 -08:00
|
|
|
"4.5.2" => { :llvm_build => 2336, :clang => "4.1", :clang_build => 421 },
|
2013-01-28 14:38:39 -06:00
|
|
|
"4.6" => { :llvm_build => 2336, :clang => "4.2", :clang_build => 425 },
|
2013-03-14 22:56:31 -05:00
|
|
|
"4.6.1" => { :llvm_build => 2336, :clang => "4.2", :clang_build => 425 },
|
2013-04-16 11:42:49 +10:00
|
|
|
"4.6.2" => { :llvm_build => 2336, :clang => "4.2", :clang_build => 425 },
|
2013-06-13 18:22:11 -05:00
|
|
|
"4.6.3" => { :llvm_build => 2336, :clang => "4.2", :clang_build => 425 },
|
2013-06-11 14:26:11 +02:00
|
|
|
"5.0" => { :clang => "5.0", :clang_build => 500 },
|
2012-06-27 12:09:57 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
def compilers_standard?
|
2013-02-10 20:59:44 -06:00
|
|
|
STANDARD_COMPILERS.fetch(Xcode.version.to_s).all? do |method, build|
|
2012-10-15 18:16:18 -05:00
|
|
|
MacOS.send(:"#{method}_version") == build
|
|
|
|
end
|
2013-02-10 20:59:44 -06:00
|
|
|
rescue IndexError
|
|
|
|
onoe <<-EOS.undent
|
|
|
|
Homebrew doesn't know what compiler versions ship with your version
|
|
|
|
of Xcode (#{Xcode.version}). 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
|
2012-06-27 12:09:57 -07:00
|
|
|
end
|
2012-06-28 12:49:54 -05:00
|
|
|
|
|
|
|
def app_with_bundle_id id
|
superenv: build-environments that just work
1. A minimal build environment, we don't set CFLAGS, CPPFLAGS, LDFLAGS, etc. the rationale being, the less that is set, the less variables we are introducing that can break builds.
2. A set of scripts that replace cc, ld, etc. and inject the -I, -L, etc. flags we need into the args passed to the build-tools.
Because we now have complete control over compiler instantiations we do a variety of clean-up tasks, like removing bad flags, enforcing universal builds and ensuring makefiles don't try to change the order of library and include paths from ones that work to ones that don't.
The previous ENV-system is still available when --env=std is specified.
superenv applies to Xcode >= 4.3 only currently.
2012-08-11 12:30:51 -04:00
|
|
|
path = mdfind(id).first
|
|
|
|
Pathname.new(path) unless path.nil? or path.empty?
|
2012-06-28 12:49:54 -05:00
|
|
|
end
|
|
|
|
|
superenv: build-environments that just work
1. A minimal build environment, we don't set CFLAGS, CPPFLAGS, LDFLAGS, etc. the rationale being, the less that is set, the less variables we are introducing that can break builds.
2. A set of scripts that replace cc, ld, etc. and inject the -I, -L, etc. flags we need into the args passed to the build-tools.
Because we now have complete control over compiler instantiations we do a variety of clean-up tasks, like removing bad flags, enforcing universal builds and ensuring makefiles don't try to change the order of library and include paths from ones that work to ones that don't.
The previous ENV-system is still available when --env=std is specified.
superenv applies to Xcode >= 4.3 only currently.
2012-08-11 12:30:51 -04:00
|
|
|
def mdfind id
|
2013-03-10 17:03:40 +00:00
|
|
|
return [] unless MACOS
|
2013-02-04 15:00:10 -06:00
|
|
|
(@mdfind ||= {}).fetch(id.to_s) do
|
|
|
|
@mdfind[id.to_s] = `/usr/bin/mdfind "kMDItemCFBundleIdentifier == '#{id}'"`.split("\n")
|
|
|
|
end
|
2012-06-28 12:49:54 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
def pkgutil_info id
|
2013-07-21 20:09:55 -05:00
|
|
|
(@pkginfo ||= {}).fetch(id.to_s) do
|
|
|
|
@pkginfo[id.to_s] = `/usr/sbin/pkgutil --pkg-info "#{id}" 2>/dev/null`.strip
|
|
|
|
end
|
2012-06-28 12:49:54 -05:00
|
|
|
end
|
2012-06-27 12:09:57 -07:00
|
|
|
end
|
2012-07-09 14:58:34 -05:00
|
|
|
|
2013-03-10 17:33:06 +00:00
|
|
|
require 'os/mac/xcode'
|
|
|
|
require 'os/mac/xquartz'
|