From 8887fe76063216c59e3f9d731fe179c2111c5d38 Mon Sep 17 00:00:00 2001 From: Jack Nagel Date: Fri, 18 Oct 2013 12:56:51 -0500 Subject: [PATCH] Move MacOS modules under OS::Mac namespace Closes Homebrew/homebrew#23138. --- Library/Homebrew/os/mac.rb | 5 +- Library/Homebrew/os/mac/version.rb | 64 ++--- Library/Homebrew/os/mac/xcode.rb | 377 +++++++++++++++-------------- Library/Homebrew/os/mac/xquartz.rb | 248 ++++++++++--------- 4 files changed, 355 insertions(+), 339 deletions(-) diff --git a/Library/Homebrew/os/mac.rb b/Library/Homebrew/os/mac.rb index d4e8e722b3..832f3f52b7 100644 --- a/Library/Homebrew/os/mac.rb +++ b/Library/Homebrew/os/mac.rb @@ -1,5 +1,7 @@ require 'hardware' require 'os/mac/version' +require 'os/mac/xcode' +require 'os/mac/xquartz' module OS module Mac @@ -270,6 +272,3 @@ module OS end end end - -require 'os/mac/xcode' -require 'os/mac/xquartz' diff --git a/Library/Homebrew/os/mac/version.rb b/Library/Homebrew/os/mac/version.rb index 4de3b91e7b..cfe42a75f5 100644 --- a/Library/Homebrew/os/mac/version.rb +++ b/Library/Homebrew/os/mac/version.rb @@ -1,39 +1,41 @@ require 'version' -module MacOS - class Version < ::Version - SYMBOLS = { - :mavericks => '10.9', - :mountain_lion => '10.8', - :lion => '10.7', - :snow_leopard => '10.6', - :leopard => '10.5', - :tiger => '10.4', - } +module OS + module Mac + class Version < ::Version + SYMBOLS = { + :mavericks => '10.9', + :mountain_lion => '10.8', + :lion => '10.7', + :snow_leopard => '10.6', + :leopard => '10.5', + :tiger => '10.4', + } - def self.from_symbol(sym) - new(SYMBOLS.fetch(sym)) - end - - def <=>(other) - v = SYMBOLS.fetch(other, other.to_s) - super(Version.new(v)) - end - - def to_sym - case @version - when '10.9' then :mavericks - when '10.8' then :mountain_lion - when '10.7' then :lion - when '10.6' then :snow_leopard - when '10.5' then :leopard - when '10.4' then :tiger - else :dunno + def self.from_symbol(sym) + new(SYMBOLS.fetch(sym)) end - end - def pretty_name - to_sym.to_s.split('_').map(&:capitalize).join(' ') + def <=>(other) + v = SYMBOLS.fetch(other, other.to_s) + super(Version.new(v)) + end + + def to_sym + case @version + when '10.9' then :mavericks + when '10.8' then :mountain_lion + when '10.7' then :lion + when '10.6' then :snow_leopard + when '10.5' then :leopard + when '10.4' then :tiger + else :dunno + end + end + + def pretty_name + to_sym.to_s.split('_').map(&:capitalize).join(' ') + end end end end diff --git a/Library/Homebrew/os/mac/xcode.rb b/Library/Homebrew/os/mac/xcode.rb index 0472f73ab5..843b3dd61b 100644 --- a/Library/Homebrew/os/mac/xcode.rb +++ b/Library/Homebrew/os/mac/xcode.rb @@ -1,203 +1,210 @@ -module MacOS::Xcode extend self +module OS + module Mac + module 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") + 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 - # NOTE!! use Xcode.prefix rather than this generally! - def folder - @folder ||= `xcode-select -print-path 2>/dev/null`.strip - end + # Locate the "current Xcode folder" via xcode-select. See: + # man xcode-select + # NOTE!! use Xcode.prefix rather than this generally! + def folder + @folder ||= `xcode-select -print-path 2>/dev/null`.strip + end - # Xcode 4.3 tools hang if "/" is set - def bad_xcode_select_path? - folder == "/" - end + # Xcode 4.3 tools hang if "/" is set + def bad_xcode_select_path? + folder == "/" + end - def latest_version - case MacOS.version - when "10.4" then "2.5" - when "10.5" then "3.1.4" - when "10.6" then "3.2.6" - when "10.7" then "4.6.3" - when "10.8" then "5.0" - when "10.9" then "5.0.1" - else - # Default to newest known version of Xcode for unreleased OSX versions. - if MacOS.version > 10.9 - "5.0.1" - else - raise "Mac OS X '#{MacOS.version}' is invalid" + def latest_version + case MacOS.version + when "10.4" then "2.5" + when "10.5" then "3.1.4" + when "10.6" then "3.2.6" + when "10.7" then "4.6.3" + when "10.8" then "5.0" + when "10.9" then "5.0.1" + else + # Default to newest known version of Xcode for unreleased OSX versions. + if MacOS.version > 10.9 + "5.0.1" + else + raise "Mac OS X '#{MacOS.version}' is invalid" + end + end + end + + def outdated? + version < latest_version + end + + def without_clt? + installed? && version >= "4.3" && !MacOS::CLT.installed? + end + + def prefix + @prefix ||= begin + path = Pathname.new(folder) + if path.absolute? and File.executable? "#{path}/usr/bin/make" + path + elsif File.executable? '/Developer/usr/bin/make' + # we do this to support cowboys who insist on installing + # only a subset of Xcode + Pathname.new('/Developer') + elsif File.executable? "#{V4_BUNDLE_PATH}/Contents/Developer/usr/bin/make" + # fallback for broken Xcode 4.3 installs + Pathname.new("#{V4_BUNDLE_PATH}/Contents/Developer") + elsif (path = bundle_path) + path += "Contents/Developer" + path if File.executable? "#{path}/usr/bin/make" + end + end + end + + # 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 + def bundle_path + MacOS.app_with_bundle_id(V4_BUNDLE_ID) || MacOS.app_with_bundle_id(V3_BUNDLE_ID) + end + + def installed? + not prefix.nil? + 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. + @version ||= uncached_version + end + + 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 OS.mac? + + # this shortcut makes version work for people who don't realise you + # need to install the CLI tools + xcode43build = Pathname.new("#{prefix}/usr/bin/xcodebuild") + if xcode43build.file? + `#{xcode43build} -version 2>/dev/null` =~ /Xcode (\d(\.\d)*)/ + return $1 if $1 + end + + # Xcode 4.3 xc* tools hang indefinately if xcode-select path is set thus + raise if bad_xcode_select_path? + + 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 + when 0 then "dunno" + 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" + when 50 then "5.0" + else "4.6" + end + end + end + + def provides_autotools? + version.to_f < 4.3 + end + + def provides_gcc? + version.to_f < 4.3 + end + + def default_prefix? + if version.to_f < 4.3 + %r{^/Developer} === prefix + else + %r{^/Applications/Xcode.app} === prefix + end end end - end - def outdated? - version < latest_version - end + module CLT + extend self - def without_clt? - installed? && version >= "4.3" && !MacOS::CLT.installed? - end + STANDALONE_PKG_ID = "com.apple.pkg.DeveloperToolsCLILeo" + FROM_XCODE_PKG_ID = "com.apple.pkg.DeveloperToolsCLI" + STANDALONE_PKG_PATH = Pathname.new("/Library/Developer/CommandLineTools") - def prefix - @prefix ||= begin - path = Pathname.new(folder) - if path.absolute? and File.executable? "#{path}/usr/bin/make" - path - elsif File.executable? '/Developer/usr/bin/make' - # we do this to support cowboys who insist on installing - # only a subset of Xcode - Pathname.new('/Developer') - elsif File.executable? "#{V4_BUNDLE_PATH}/Contents/Developer/usr/bin/make" - # fallback for broken Xcode 4.3 installs - Pathname.new("#{V4_BUNDLE_PATH}/Contents/Developer") - elsif (path = bundle_path) - path += "Contents/Developer" - path if File.executable? "#{path}/usr/bin/make" + # True if: + # - Xcode < 4.3 is installed. The tools are found under /usr. + # - The "Command Line Tools" package has been installed + # For OS X < 10.9, the tools are found under /usr. For 10.9, + # they are found under /Library/Developer/CommandLineTools. + def installed? + mavericks_dev_tools? || usr_dev_tools? end - end - end - # 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 - def bundle_path - MacOS.app_with_bundle_id(V4_BUNDLE_ID) || MacOS.app_with_bundle_id(V3_BUNDLE_ID) - end - - def installed? - not prefix.nil? - 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. - @version ||= uncached_version - end - - 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 OS.mac? - - # this shortcut makes version work for people who don't realise you - # need to install the CLI tools - xcode43build = Pathname.new("#{prefix}/usr/bin/xcodebuild") - if xcode43build.file? - `#{xcode43build} -version 2>/dev/null` =~ /Xcode (\d(\.\d)*)/ - return $1 if $1 - end - - # Xcode 4.3 xc* tools hang indefinately if xcode-select path is set thus - raise if bad_xcode_select_path? - - 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 - when 0 then "dunno" - 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" - when 50 then "5.0" - else "4.6" + def mavericks_dev_tools? + MacOS.dev_tools_path == Pathname("#{STANDALONE_PKG_PATH}/usr/bin") && + File.directory?("#{STANDALONE_PKG_PATH}/usr/include") end - end - end - def provides_autotools? - version.to_f < 4.3 - end + def usr_dev_tools? + MacOS.dev_tools_path == Pathname("/usr/bin") && File.directory?("/usr/include") + end - def provides_gcc? - version.to_f < 4.3 - end + def latest_version? + `/usr/bin/clang --version` =~ %r{clang-(\d+)\.(\d+)\.(\d+)} + $1.to_i >= 425 and $3.to_i >= 28 + end - def default_prefix? - if version.to_f < 4.3 - %r{^/Developer} === prefix - else - %r{^/Applications/Xcode.app} === prefix - end - end -end - -module MacOS::CLT extend self - STANDALONE_PKG_ID = "com.apple.pkg.DeveloperToolsCLILeo" - FROM_XCODE_PKG_ID = "com.apple.pkg.DeveloperToolsCLI" - STANDALONE_PKG_PATH = Pathname.new("/Library/Developer/CommandLineTools") - - # True if: - # - Xcode < 4.3 is installed. The tools are found under /usr. - # - The "Command Line Tools" package has been installed - # For OS X < 10.9, the tools are found under /usr. For 10.9, - # they are found under /Library/Developer/CommandLineTools. - def installed? - mavericks_dev_tools? || usr_dev_tools? - end - - def mavericks_dev_tools? - MacOS.dev_tools_path == Pathname("#{STANDALONE_PKG_PATH}/usr/bin") && - File.directory?("#{STANDALONE_PKG_PATH}/usr/include") - end - - def usr_dev_tools? - MacOS.dev_tools_path == Pathname("/usr/bin") && File.directory?("/usr/include") - end - - def latest_version? - `/usr/bin/clang --version` =~ %r{clang-(\d+)\.(\d+)\.(\d+)} - $1.to_i >= 425 and $3.to_i >= 28 - end - - def outdated? - !latest_version? - end - - # Version string (a pretty damn long one) of the CLT package. - # Note, that different ways to install the CLTs lead to different - # version numbers. - def version - @version ||= detect_version - end - - def detect_version - [STANDALONE_PKG_ID, FROM_XCODE_PKG_ID].find do |id| - version = MacOS.pkgutil_info(id)[/version: (.+)$/, 1] - return version if version + def outdated? + !latest_version? + end + + # Version string (a pretty damn long one) of the CLT package. + # Note, that different ways to install the CLTs lead to different + # version numbers. + def version + @version ||= detect_version + end + + def detect_version + [STANDALONE_PKG_ID, FROM_XCODE_PKG_ID].find do |id| + version = MacOS.pkgutil_info(id)[/version: (.+)$/, 1] + return version if version + end + end end end end diff --git a/Library/Homebrew/os/mac/xquartz.rb b/Library/Homebrew/os/mac/xquartz.rb index 418550aa80..82680d3ba2 100644 --- a/Library/Homebrew/os/mac/xquartz.rb +++ b/Library/Homebrew/os/mac/xquartz.rb @@ -1,131 +1,139 @@ -module MacOS::XQuartz extend self - FORGE_BUNDLE_ID = "org.macosforge.xquartz.X11" - APPLE_BUNDLE_ID = "org.x.X11" - FORGE_PKG_ID = "org.macosforge.xquartz.pkg" +module OS + module Mac + module XQuartz + extend self - PKGINFO_VERSION_MAP = { - "2.6.34" => "2.6.3", - "2.7.4" => "2.7.0", - "2.7.14" => "2.7.1", - "2.7.28" => "2.7.2", - "2.7.32" => "2.7.3", - "2.7.43" => "2.7.4", - "2.7.50" => "2.7.5_rc1", - "2.7.51" => "2.7.5_rc2", - }.freeze + FORGE_BUNDLE_ID = "org.macosforge.xquartz.X11" + APPLE_BUNDLE_ID = "org.x.X11" + FORGE_PKG_ID = "org.macosforge.xquartz.pkg" - # This returns the version number of XQuartz, not of the upstream X.org. - # The X11.app distributed by Apple is also XQuartz, and therefore covered - # by this method. - def version - @version ||= detect_version - end + PKGINFO_VERSION_MAP = { + "2.6.34" => "2.6.3", + "2.7.4" => "2.7.0", + "2.7.14" => "2.7.1", + "2.7.28" => "2.7.2", + "2.7.32" => "2.7.3", + "2.7.43" => "2.7.4", + "2.7.50" => "2.7.5_rc1", + "2.7.51" => "2.7.5_rc2", + }.freeze - def detect_version - if (path = bundle_path) && path.exist? && (version = version_from_mdls(path)) - version - elsif prefix.to_s == "/usr/X11" - guess_system_version - else - version_from_pkgutil + # This returns the version number of XQuartz, not of the upstream X.org. + # The X11.app distributed by Apple is also XQuartz, and therefore covered + # by this method. + def version + @version ||= detect_version + end + + def detect_version + if (path = bundle_path) && path.exist? && (version = version_from_mdls(path)) + version + elsif prefix.to_s == "/usr/X11" + guess_system_version + else + version_from_pkgutil + end + end + + def latest_version + "2.7.4" + end + + def bundle_path + MacOS.app_with_bundle_id(FORGE_BUNDLE_ID) || MacOS.app_with_bundle_id(APPLE_BUNDLE_ID) + end + + def version_from_mdls(path) + version = `mdls -raw -nullMarker "" -name kMDItemVersion "#{path}" 2>/dev/null`.strip + version unless version.empty? + end + + # The XQuartz that Apple shipped in OS X through 10.7 does not have a + # pkg-util entry, so if Spotlight indexing is disabled we must make an + # educated guess as to what version is installed. + def guess_system_version + case MacOS.version + when '10.5' then '2.1.6' + when '10.6' then '2.3.6' + when '10.7' then '2.6.3' + else 'dunno' + end + end + + # Upstream XQuartz *does* have a pkg-info entry, so if we can't get it + # from mdls, we can try pkgutil. This is very slow. + def version_from_pkgutil + str = MacOS.pkgutil_info(FORGE_PKG_ID)[/version: (\d\.\d\.\d+)$/, 1] + PKGINFO_VERSION_MAP.fetch(str, str) + end + + def provided_by_apple? + [FORGE_BUNDLE_ID, APPLE_BUNDLE_ID].find do |id| + MacOS.app_with_bundle_id(id) + end == APPLE_BUNDLE_ID + end + + # This should really be private, but for compatibility reasons it must + # remain public. New code should use MacOS::X11.{bin,lib,include} + # instead, as that accounts for Xcode-only systems. + def prefix + @prefix ||= if Pathname.new('/opt/X11/lib/libpng.dylib').exist? + Pathname.new('/opt/X11') + elsif Pathname.new('/usr/X11/lib/libpng.dylib').exist? + Pathname.new('/usr/X11') + end + end + + def installed? + !version.nil? && !prefix.nil? + end end - end - def latest_version - "2.7.4" - end + module X11 + extend self - def bundle_path - MacOS.app_with_bundle_id(FORGE_BUNDLE_ID) || MacOS.app_with_bundle_id(APPLE_BUNDLE_ID) - end + def prefix + MacOS::XQuartz.prefix + end - def version_from_mdls(path) - version = `mdls -raw -nullMarker "" -name kMDItemVersion "#{path}" 2>/dev/null`.strip - version unless version.empty? - end + def installed? + MacOS::XQuartz.installed? + end - # The XQuartz that Apple shipped in OS X through 10.7 does not have a - # pkg-util entry, so if Spotlight indexing is disabled we must make an - # educated guess as to what version is installed. - def guess_system_version - case MacOS.version - when '10.5' then '2.1.6' - when '10.6' then '2.3.6' - when '10.7' then '2.6.3' - else 'dunno' + # If XQuartz and/or the CLT are installed, headers will be found under + # /opt/X11/include or /usr/X11/include. For Xcode-only systems, they are + # found in the SDK, so we use sdk_path for both the headers and libraries. + # Confusingly, executables (e.g. config scripts) are only found under + # /opt/X11/bin or /usr/X11/bin in all cases. + def bin + Pathname.new("#{prefix}/bin") + end + + def include + @include ||= if use_sdk? + Pathname.new("#{MacOS.sdk_path}/usr/X11/include") + else + Pathname.new("#{prefix}/include") + end + end + + def lib + @lib ||= if use_sdk? + Pathname.new("#{MacOS.sdk_path}/usr/X11/lib") + else + Pathname.new("#{prefix}/lib") + end + end + + def share + Pathname.new("#{prefix}/share") + end + + private + + def use_sdk? + not (prefix.to_s == '/opt/X11' or MacOS::CLT.installed?) + end end end - - # Upstream XQuartz *does* have a pkg-info entry, so if we can't get it - # from mdls, we can try pkgutil. This is very slow. - def version_from_pkgutil - str = MacOS.pkgutil_info(FORGE_PKG_ID)[/version: (\d\.\d\.\d+)$/, 1] - PKGINFO_VERSION_MAP.fetch(str, str) - end - - def provided_by_apple? - [FORGE_BUNDLE_ID, APPLE_BUNDLE_ID].find do |id| - MacOS.app_with_bundle_id(id) - end == APPLE_BUNDLE_ID - end - - # This should really be private, but for compatibility reasons it must - # remain public. New code should use MacOS::X11.{bin,lib,include} - # instead, as that accounts for Xcode-only systems. - def prefix - @prefix ||= if Pathname.new('/opt/X11/lib/libpng.dylib').exist? - Pathname.new('/opt/X11') - elsif Pathname.new('/usr/X11/lib/libpng.dylib').exist? - Pathname.new('/usr/X11') - end - end - - def installed? - !version.nil? && !prefix.nil? - end -end - -module MacOS::X11 extend self - def prefix - MacOS::XQuartz.prefix - end - - def installed? - MacOS::XQuartz.installed? - end - - # If XQuartz and/or the CLT are installed, headers will be found under - # /opt/X11/include or /usr/X11/include. For Xcode-only systems, they are - # found in the SDK, so we use sdk_path for both the headers and libraries. - # Confusingly, executables (e.g. config scripts) are only found under - # /opt/X11/bin or /usr/X11/bin in all cases. - def bin - Pathname.new("#{prefix}/bin") - end - - def include - @include ||= if use_sdk? - Pathname.new("#{MacOS.sdk_path}/usr/X11/include") - else - Pathname.new("#{prefix}/include") - end - end - - def lib - @lib ||= if use_sdk? - Pathname.new("#{MacOS.sdk_path}/usr/X11/lib") - else - Pathname.new("#{prefix}/lib") - end - end - - def share - Pathname.new("#{prefix}/share") - end - - private - - def use_sdk? - not (prefix.to_s == '/opt/X11' or MacOS::CLT.installed?) - end end