diff options
| author | samueljohn | 2012-02-26 21:04:15 +0100 |
|---|---|---|
| committer | Adam Vandenberg | 2012-06-24 19:11:06 -0700 |
| commit | 725feb3db1da1577a3e1b376934e16aedbd9ded9 (patch) | |
| tree | 442b4168dde06a09e242a0ab7d4204e274ad60ce /Library/Homebrew/utils.rb | |
| parent | 3147dd134a6e919c974b4a8abc93338d489cc31a (diff) | |
| download | brew-725feb3db1da1577a3e1b376934e16aedbd9ded9.tar.bz2 | |
Core change: XCode only install, with CLT or both
Allow XCode without the Command Line Tools to
work with homebrew, so it's not necessary
to register an Apple Dev ID and/or go to the
XCode prefs and download the CLT. Yay!
Further, this commit allows to use the CLT
solely (without the need for XCode).
Saves quite some megs.
(Some furmulae require xcodebuild)
Of course XCode together with the CLT is still
fine and has been tested on 10.7 and 10.6
with Xcode 4 and Xcode 3.
Only on Lion or above, tell the user about the options,
which are
- Xcode without CLT
- CLT without Xcode
- both (ok, it's not directly stated, but implicit)
So if no Xcode is found and we are on Lion or above,
we don't fail but check for the CLTs now.
For older Macs, the old message that Xcode is needed
and the installer should be run is still displayed.
If the CLT are not found but Xcode is, then we
print out about the experimental status of this setup.
Closes Homebrew/homebrew#10510.
Signed-off-by: Adam Vandenberg <flangy@gmail.com>
Diffstat (limited to 'Library/Homebrew/utils.rb')
| -rw-r--r-- | Library/Homebrew/utils.rb | 186 |
1 files changed, 156 insertions, 30 deletions
diff --git a/Library/Homebrew/utils.rb b/Library/Homebrew/utils.rb index 1ee4232ec..21ce26940 100644 --- a/Library/Homebrew/utils.rb +++ b/Library/Homebrew/utils.rb @@ -254,41 +254,139 @@ module MacOS extend self end end + def clt_installed? + # If the command line tools are installed, most unix standard + # tools, libs and headers are in /usr. + # Returns true, also for older Xcode/OSX versions that had everything in /usr + # Beginning with Xcode 4.3, the dev tools are no longer installed + # in /usr and SDKs no longer in /Developer by default. + # But Apple provides an optional "Command Line Tools for Xcode" package. + not clt_version.empty? or dev_tools_path == Pathname.new("/usr/bin") + end + + def clt_version + # Version string (a pretty damn long one) of the CLT package. + # Note, that different ways to install the CLTs lead to different + # version numbers. + @clt_version ||= begin + # CLT installed via stand-alone website download + clt_pkginfo_stand_alone = `pkgutil --pkg-info com.apple.pkg.DeveloperToolsCLILeo 2>/dev/null`.strip + # CLT installed via preferences from within Xcode + clt_pkginfo_from_xcode = `pkgutil --pkg-info com.apple.pkg.DeveloperToolsCLI 2>/dev/null`.strip + if not clt_pkginfo_stand_alone.empty? + clt_pkginfo_stand_alone =~ /version: (.*)$/ + $1 + elsif not clt_pkginfo_from_xcode.empty? + clt_pkginfo_from_xcode =~ /version: (.*)$/ + $1 + else + # We return "" instead of nil because we want clt_installed? to be true on older Macs. + # So clt_version.empty? does not mean there are no unix tools in /usr, it just means + # that the "Command Line Tools for Xcode" package is not installed + "" # No CLT or recipe available to pkgutil. + end + 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. + tool = tool.to_s + + @locate_cache ||= {} + return @locate_cache[tool] if @locate_cache.has_key? tool + + if File.executable? "/usr/bin/#{tool}" + path = Pathname.new "/usr/bin/#{tool}" + elsif not MacOS.xctools_fucked? and system "/usr/bin/xcrun -find #{tool} 1>/dev/null 2>&1" + # xcrun was provided first with Xcode 4.3 and allows us to proxy + # tool usage thus avoiding various bugs + p = `/usr/bin/xcrun -find #{tool}`.chomp + if File.executable? p + path = Pathname.new p + else + path = nil + end + else + # otherwise lets try and figure it out ourselves + p = "#{MacOS.dev_tools_path}/#{tool}" + if File.executable? p + path = Pathname.new p + else + # This is for the use-case where xcode-select is not set up with + # Xcode 4.3+. The tools in Xcode 4.3+ are split over two locations, + # usually xcrun would figure that out for us, but it won't work if + # xcode-select is not configured properly (i.e. xctools_fucked?). + p = "#{MacOS.xcode_prefix}/Toolchains/XcodeDefault.xctoolchain/usr/bin/#{tool}" + if File.executable? p + path Pathname.new p + else + path = nil + end + end + end + @locate_cache[tool] = path + return path + end + def dev_tools_path - @dev_tools_path ||= if File.file? "/usr/bin/cc" and File.file? "/usr/bin/make" - # probably a safe enough assumption - "/usr/bin" - elsif File.file? "#{xcode_prefix}/usr/bin/make" + @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" + elsif not xctools_fucked? + # The new way of finding stuff via locate: + Pathname.new(locate 'make').dirname + elsif File.exist? "#{xcode_prefix}/usr/bin/make" # cc stopped existing with Xcode 4.3, there are c89 and c99 options though - "#{xcode_prefix}/usr/bin" + Pathname.new "#{xcode_prefix}/usr/bin" else # yes this seems dumb, but we can't throw because the existance of # dev tools is not mandatory for installing formula. Eventually we # should make formula specify if they need dev tools or not. - "/usr/bin" + Pathname.new "/usr/bin" end end - def xctools_fucked? - # Xcode 4.3 tools hang if "/" is set - `/usr/bin/xcode-select -print-path 2>/dev/null`.chomp == "/" + def xctoolchain_path + # Beginning with Xcode 4.3, clang and some other tools are located in a xctoolchain dir. + @xctoolchain_path ||= begin + path = Pathname.new("#{MacOS.xcode_prefix}/Toolchains/XcodeDefault.xctoolchain") + if path.exist? + path + else + # ok, there are no Toolchains in xcode_prefix + # and that's ok as long as everything is in dev_tools_path="/usr/bin" (i.e. clt_installed?) + nil + end + end end - def default_cc - cc = unless xctools_fucked? - out = `/usr/bin/xcrun -find cc 2> /dev/null`.chomp - out if $?.success? + def sdk_path(v=MacOS.version) + # The path of the MacOSX SDK. + if not MacOS.xctools_fucked? + path = `#{locate('xcodebuild')} -version -sdk macosx#{v} Path 2>/dev/null`.chomp + elsif File.directory? '/Developer/SDKs/MacOS#{v}.sdk' + # the old default (or wild wild west style) + path = "/Developer/SDKs/MacOS#{v}.sdk" + elsif File.directory? "#{xcode_prefix}/Platforms/MacOSX.platform/Developer/SDKs/MacOSX#{v}.sdk" + # xcode_prefix is pretty smart, so lets look inside to find the sdk + path = "#{xcode_prefix}/Platforms/MacOSX.platform/Developer/SDKs/MacOSX#{v}.sdk" end - cc = "#{dev_tools_path}/cc" if cc.nil? or cc.empty? - - unless File.executable? cc - # If xcode-select isn't setup then xcrun fails and on Xcode 4.3 - # the cc binary is not at #{dev_tools_path}. This return is almost - # worthless however since in this particular setup nothing much builds - # but I wrote the code now and maybe we'll fix the other issues later. - cc = "#{xcode_prefix}/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc" + if path.nil? or path.empty? or not File.directory? path + nil + else + Pathname.new path end + end + def xctools_fucked? + # Xcode 4.3 tools hang if "/" is set + @xctools_fucked ||= `/usr/bin/xcode-select -print-path 2>/dev/null`.chomp == "/" + end + + def default_cc + cc = locate 'cc' Pathname.new(cc).realpath.basename.to_s rescue nil end @@ -341,18 +439,45 @@ module MacOS extend self # Ask Spotlight where Xcode is. If the user didn't install the # helper tools and installed Xcode in a non-conventional place, this # is our only option. See: http://superuser.com/questions/390757 - path = `mdfind "kMDItemDisplayName==Xcode&&kMDItemKind==Application"` + path = `mdfind "kMDItemCFBundleIdentifier == 'com.apple.dt.Xcode'"`.strip + if path.empty? + # Xcode 3 had a different identifier + path = `mdfind "kMDItemCFBundleIdentifier == 'com.apple.Xcode'"`.strip + end path = "#{path}/Contents/Developer" if path.empty? or not File.directory? path nil else - path + Pathname.new path end end end end - def xcode_version + def xcode_installed? + # Telling us whether the Xcode.app is installed or not. + @xcode_installed ||= begin + if File.directory? '/Applications/Xcode.app' + true + elsif File.directory? '/Developer/Applications/Xcode.app' # old style + true + elsif not `mdfind "kMDItemCFBundleIdentifier == 'com.apple.dt.Xcode'"`.strip.empty? + # Xcode 4 + true + elsif not `mdfind "kMDItemCFBundleIdentifier == 'com.apple.Xcode'"`.strip.empty? + # Xcode 3 + true + else + false + end + end + end + + + def xcode_version + # may return a version string + # that is guessed based on the compiler, so do not + # use it in order to check if Xcode is installed. @xcode_version ||= begin return "0" unless MACOS @@ -417,27 +542,28 @@ module MacOS extend self 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 File.exist? "#{dev_tools_path}/llvm-gcc" - `#{dev_tools_path}/llvm-gcc --version` =~ /LLVM build (\d{4,})/ + @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 File.exist? "#{dev_tools_path}/clang" - `#{dev_tools_path}/clang --version` =~ /clang version (\d\.\d)/ + @clang_version ||= if locate("clang") + `#{locate("clang")} --version` =~ /clang version (\d\.\d)/ $1 end end def clang_build_version - @clang_build_version ||= if File.exist? "#{dev_tools_path}/clang" - `#{dev_tools_path}/clang --version` =~ %r[tags/Apple/clang-(\d{2,})] + @clang_build_version ||= if locate("clang") + `#{locate("clang")} --version` =~ %r[tags/Apple/clang-(\d{2,})] $1.to_i end end def x11_installed? + # Even if only Xcode (without CLT) is installed, this dylib is there. Pathname.new('/usr/X11/lib/libpng.dylib').exist? end |
