| 
									
										
										
										
											2012-07-09 15:18:02 -05:00
										 |  |  | module MacOS::Xcode extend self | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   V4_BUNDLE_ID = "com.apple.dt.Xcode" | 
					
						
							|  |  |  |   V3_BUNDLE_ID = "com.apple.Xcode" | 
					
						
							|  |  |  |   V4_BUNDLE_PATH = Pathname.new("/Applications/Xcode.app") | 
					
						
							|  |  |  |   V3_BUNDLE_PATH = Pathname.new("/Developer/Applications/Xcode.app") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   # Locate the "current Xcode folder" via xcode-select. See: | 
					
						
							|  |  |  |   # man xcode-select | 
					
						
							| 
									
										
										
										
											2012-08-31 09:51:08 -04:00
										 |  |  |   # NOTE!! use Xcode.prefix rather than this generally! | 
					
						
							| 
									
										
										
										
											2012-07-09 15:18:02 -05:00
										 |  |  |   def folder | 
					
						
							|  |  |  |     @folder ||= `xcode-select -print-path 2>/dev/null`.strip | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   # Xcode 4.3 tools hang if "/" is set | 
					
						
							| 
									
										
										
										
											2012-07-12 03:10:57 -05:00
										 |  |  |   def bad_xcode_select_path? | 
					
						
							| 
									
										
										
										
											2012-07-09 15:18:02 -05:00
										 |  |  |     folder == "/" | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-17 17:18:17 -04:00
										 |  |  |   def latest_version | 
					
						
							|  |  |  |     case MacOS.version | 
					
						
							| 
									
										
										
										
											2013-05-23 18:44:50 -05:00
										 |  |  |     when 10.4       then "2.5" | 
					
						
							| 
									
										
										
										
											2013-05-22 22:26:09 -05:00
										 |  |  |     when 10.5       then "3.1.4" | 
					
						
							|  |  |  |     when 10.6       then "3.2.6" | 
					
						
							| 
									
										
										
										
											2013-05-22 22:59:38 -05:00
										 |  |  |     when 10.7, 10.8 then "4.6.2" | 
					
						
							| 
									
										
										
										
											2012-08-17 17:18:17 -04:00
										 |  |  |     else | 
					
						
							| 
									
										
										
										
											2013-05-22 22:26:09 -05:00
										 |  |  |       raise "Mac OS X '#{MacOS.version}' is invalid" | 
					
						
							| 
									
										
										
										
											2012-08-17 17:18:17 -04:00
										 |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-22 22:26:09 -05:00
										 |  |  |   def outdated? | 
					
						
							|  |  |  |     version < latest_version | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-09 15:18:02 -05:00
										 |  |  |   def prefix | 
					
						
							|  |  |  |     @prefix ||= begin | 
					
						
							| 
									
										
										
										
											2012-08-31 09:51:08 -04:00
										 |  |  |       path = Pathname.new(folder) | 
					
						
							| 
									
										
										
										
											2013-04-15 15:00:57 -05:00
										 |  |  |       if path.absolute? and File.executable? "#{path}/usr/bin/make" | 
					
						
							| 
									
										
										
										
											2012-07-09 15:18:02 -05:00
										 |  |  |         path | 
					
						
							|  |  |  |       elsif File.executable? '/Developer/usr/bin/make' | 
					
						
							|  |  |  |         # we do this to support cowboys who insist on installing | 
					
						
							|  |  |  |         # only a subset of Xcode | 
					
						
							| 
									
										
										
										
											2013-04-15 15:00:57 -05:00
										 |  |  |         Pathname.new('/Developer') | 
					
						
							|  |  |  |       elsif File.executable? "#{V4_BUNDLE_PATH}/Contents/Developer/usr/bin/make" | 
					
						
							| 
									
										
										
										
											2012-07-09 15:18:02 -05:00
										 |  |  |         # fallback for broken Xcode 4.3 installs | 
					
						
							| 
									
										
										
										
											2013-04-15 15:00:57 -05:00
										 |  |  |         Pathname.new("#{V4_BUNDLE_PATH}/Contents/Developer") | 
					
						
							| 
									
										
										
										
											2012-07-09 15:18:02 -05:00
										 |  |  |       else | 
					
						
							|  |  |  |         # 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 = MacOS.app_with_bundle_id(V4_BUNDLE_ID) || | 
					
						
							|  |  |  |           MacOS.app_with_bundle_id(V3_BUNDLE_ID) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         unless path.nil? | 
					
						
							|  |  |  |           path += "Contents/Developer" | 
					
						
							| 
									
										
										
										
											2013-04-15 15:00:57 -05:00
										 |  |  |           path if File.executable? "#{path}/usr/bin/make" | 
					
						
							| 
									
										
										
										
											2012-07-09 15:18:02 -05:00
										 |  |  |         end | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   def installed? | 
					
						
							| 
									
										
										
										
											2012-12-29 17:16:38 -06:00
										 |  |  |     not prefix.nil? | 
					
						
							| 
									
										
										
										
											2012-07-09 15:18:02 -05:00
										 |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   def 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. | 
					
						
							| 
									
										
										
										
											2012-08-06 13:46:02 -04:00
										 |  |  |     @version ||= uncached_version | 
					
						
							|  |  |  |   end | 
					
						
							| 
									
										
										
										
											2012-07-09 15:18:02 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-06 13:46:02 -04:00
										 |  |  |   def uncached_version | 
					
						
							|  |  |  |     # This is a separate function as you can't cache the value out of a block | 
					
						
							|  |  |  |     # if return is used in the middle, which we do many times in here. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return "0" unless MACOS | 
					
						
							| 
									
										
										
										
											2012-07-09 15:18:02 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-06 13:46:02 -04:00
										 |  |  |     # this shortcut makes version work for people who don't realise you | 
					
						
							|  |  |  |     # need to install the CLI tools | 
					
						
							| 
									
										
										
										
											2013-04-15 15:00:57 -05:00
										 |  |  |     xcode43build = Pathname.new("#{prefix}/usr/bin/xcodebuild") | 
					
						
							| 
									
										
										
										
											2012-08-06 13:46:02 -04:00
										 |  |  |     if xcode43build.file? | 
					
						
							|  |  |  |       `#{xcode43build} -version 2>/dev/null` =~ /Xcode (\d(\.\d)*)/ | 
					
						
							| 
									
										
										
										
											2012-08-07 14:34:27 -04:00
										 |  |  |       return $1 if $1 | 
					
						
							| 
									
										
										
										
											2012-08-06 13:46:02 -04:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Xcode 4.3 xc* tools hang indefinately if xcode-select path is set thus | 
					
						
							|  |  |  |     raise if bad_xcode_select_path? | 
					
						
							| 
									
										
										
										
											2012-07-09 15:18:02 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-06 13:46:02 -04:00
										 |  |  |     raise unless which "xcodebuild" | 
					
						
							|  |  |  |     `xcodebuild -version 2>/dev/null` =~ /Xcode (\d(\.\d)*)/ | 
					
						
							|  |  |  |     raise if $1.nil? or not $?.success? | 
					
						
							|  |  |  |     $1 | 
					
						
							|  |  |  |   rescue | 
					
						
							|  |  |  |     # For people who's xcode-select is unset, or who have installed | 
					
						
							|  |  |  |     # xcode-gcc-installer or whatever other combinations we can try and | 
					
						
							|  |  |  |     # supprt. See https://github.com/mxcl/homebrew/wiki/Xcode | 
					
						
							|  |  |  |     case MacOS.llvm_build_version.to_i | 
					
						
							|  |  |  |     when 1..2063 then "3.1.0" | 
					
						
							|  |  |  |     when 2064..2065 then "3.1.4" | 
					
						
							|  |  |  |     when 2366..2325
 | 
					
						
							|  |  |  |       # we have no data for this range so we are guessing | 
					
						
							|  |  |  |       "3.2.0" | 
					
						
							|  |  |  |     when 2326
 | 
					
						
							|  |  |  |       # also applies to "3.2.3" | 
					
						
							|  |  |  |       "3.2.4" | 
					
						
							|  |  |  |     when 2327..2333 then "3.2.5" | 
					
						
							|  |  |  |     when 2335
 | 
					
						
							|  |  |  |       # this build number applies to 3.2.6, 4.0 and 4.1 | 
					
						
							|  |  |  |       # https://github.com/mxcl/homebrew/wiki/Xcode | 
					
						
							|  |  |  |       "4.0" | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |       case (MacOS.clang_version.to_f * 10).to_i | 
					
						
							| 
									
										
										
										
											2013-02-04 14:42:37 -06:00
										 |  |  |       when 0       then "dunno" | 
					
						
							| 
									
										
										
										
											2013-01-29 09:51:01 -06:00
										 |  |  |       when 1..14   then "3.2.2" | 
					
						
							|  |  |  |       when 15      then "3.2.4" | 
					
						
							|  |  |  |       when 16      then "3.2.5" | 
					
						
							|  |  |  |       when 17..20  then "4.0" | 
					
						
							|  |  |  |       when 21      then "4.1" | 
					
						
							|  |  |  |       when 22..30  then "4.2" | 
					
						
							|  |  |  |       when 31      then "4.3" | 
					
						
							|  |  |  |       when 40      then "4.4" | 
					
						
							|  |  |  |       when 41      then "4.5" | 
					
						
							|  |  |  |       when 42      then "4.6" | 
					
						
							|  |  |  |       else "4.6" | 
					
						
							| 
									
										
										
										
											2012-07-09 15:18:02 -05:00
										 |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							| 
									
										
										
										
											2012-07-09 15:19:30 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |   def provides_autotools? | 
					
						
							|  |  |  |     version.to_f < 4.3
 | 
					
						
							|  |  |  |   end | 
					
						
							| 
									
										
										
										
											2012-07-10 21:01:16 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |   def provides_gcc? | 
					
						
							|  |  |  |     version.to_f < 4.3
 | 
					
						
							|  |  |  |   end | 
					
						
							| 
									
										
										
										
											2012-09-14 13:24:28 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |   def default_prefix? | 
					
						
							|  |  |  |     if version.to_f < 4.3
 | 
					
						
							|  |  |  |       %r{^/Developer} === prefix | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |       %r{^/Applications/Xcode.app} === prefix | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							| 
									
										
										
										
											2012-07-09 15:18:02 -05:00
										 |  |  | end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | module MacOS::CLT extend self | 
					
						
							|  |  |  |   STANDALONE_PKG_ID = "com.apple.pkg.DeveloperToolsCLILeo" | 
					
						
							|  |  |  |   FROM_XCODE_PKG_ID = "com.apple.pkg.DeveloperToolsCLI" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   # This is true ift he standard UNIX tools are present under /usr. For | 
					
						
							|  |  |  |   # Xcode < 4.3, this is the standard location. Otherwise, it means that | 
					
						
							|  |  |  |   # the user has installed the "Command Line Tools for Xcode" package. | 
					
						
							|  |  |  |   def installed? | 
					
						
							|  |  |  |     MacOS.dev_tools_path == Pathname.new("/usr/bin") | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-17 17:18:17 -04:00
										 |  |  |   def latest_version? | 
					
						
							| 
									
										
										
										
											2013-01-29 07:44:19 -06:00
										 |  |  |     `/usr/bin/clang --version` =~ %r{clang-(\d+)\.(\d+)\.(\d+)} | 
					
						
							| 
									
										
										
										
											2013-04-16 11:42:49 +10:00
										 |  |  |     $1.to_i >= 425 and $3.to_i >= 28
 | 
					
						
							| 
									
										
										
										
											2012-08-17 17:18:17 -04:00
										 |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-22 22:26:09 -05:00
										 |  |  |   def outdated? | 
					
						
							|  |  |  |     !latest_version? | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-09 15:18:02 -05:00
										 |  |  |   def version | 
					
						
							| 
									
										
										
										
											2012-08-27 12:57:34 -04:00
										 |  |  |     # The pkgutils calls are slow, don't repeat if no CLT installed. | 
					
						
							| 
									
										
										
										
											2012-09-03 16:35:03 -04:00
										 |  |  |     return @version if @version_determined | 
					
						
							| 
									
										
										
										
											2012-08-27 12:57:34 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     @version_determined = true | 
					
						
							| 
									
										
										
										
											2012-07-09 15:18:02 -05:00
										 |  |  |     # Version string (a pretty damn long one) of the CLT package. | 
					
						
							|  |  |  |     # Note, that different ways to install the CLTs lead to different | 
					
						
							|  |  |  |     # version numbers. | 
					
						
							| 
									
										
										
										
											2012-08-27 12:57:34 -04:00
										 |  |  |     @version ||= [STANDALONE_PKG_ID, FROM_XCODE_PKG_ID].find do |id| | 
					
						
							|  |  |  |       MacOS.pkgutil_info(id) =~ /version: (.+)$/ | 
					
						
							|  |  |  |     end && $1 | 
					
						
							| 
									
										
										
										
											2012-07-09 15:18:02 -05:00
										 |  |  |   end | 
					
						
							|  |  |  | end |