Move MacOS modules under OS::Mac namespace

Closes Homebrew/homebrew#23138.
This commit is contained in:
Jack Nagel 2013-10-18 12:56:51 -05:00
parent 805472946b
commit 8887fe7606
4 changed files with 355 additions and 339 deletions

View File

@ -1,5 +1,7 @@
require 'hardware' require 'hardware'
require 'os/mac/version' require 'os/mac/version'
require 'os/mac/xcode'
require 'os/mac/xquartz'
module OS module OS
module Mac module Mac
@ -270,6 +272,3 @@ module OS
end end
end end
end end
require 'os/mac/xcode'
require 'os/mac/xquartz'

View File

@ -1,39 +1,41 @@
require 'version' require 'version'
module MacOS module OS
class Version < ::Version module Mac
SYMBOLS = { class Version < ::Version
:mavericks => '10.9', SYMBOLS = {
:mountain_lion => '10.8', :mavericks => '10.9',
:lion => '10.7', :mountain_lion => '10.8',
:snow_leopard => '10.6', :lion => '10.7',
:leopard => '10.5', :snow_leopard => '10.6',
:tiger => '10.4', :leopard => '10.5',
} :tiger => '10.4',
}
def self.from_symbol(sym) def self.from_symbol(sym)
new(SYMBOLS.fetch(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
end end
end
def pretty_name def <=>(other)
to_sym.to_s.split('_').map(&:capitalize).join(' ') 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 end
end end

View File

@ -1,203 +1,210 @@
module MacOS::Xcode extend self module OS
module Mac
module Xcode
extend self
V4_BUNDLE_ID = "com.apple.dt.Xcode" V4_BUNDLE_ID = "com.apple.dt.Xcode"
V3_BUNDLE_ID = "com.apple.Xcode" V3_BUNDLE_ID = "com.apple.Xcode"
V4_BUNDLE_PATH = Pathname.new("/Applications/Xcode.app") V4_BUNDLE_PATH = Pathname.new("/Applications/Xcode.app")
V3_BUNDLE_PATH = Pathname.new("/Developer/Applications/Xcode.app") V3_BUNDLE_PATH = Pathname.new("/Developer/Applications/Xcode.app")
# Locate the "current Xcode folder" via xcode-select. See: # Locate the "current Xcode folder" via xcode-select. See:
# man xcode-select # man xcode-select
# NOTE!! use Xcode.prefix rather than this generally! # NOTE!! use Xcode.prefix rather than this generally!
def folder def folder
@folder ||= `xcode-select -print-path 2>/dev/null`.strip @folder ||= `xcode-select -print-path 2>/dev/null`.strip
end end
# Xcode 4.3 tools hang if "/" is set # Xcode 4.3 tools hang if "/" is set
def bad_xcode_select_path? def bad_xcode_select_path?
folder == "/" folder == "/"
end end
def latest_version def latest_version
case MacOS.version case MacOS.version
when "10.4" then "2.5" when "10.4" then "2.5"
when "10.5" then "3.1.4" when "10.5" then "3.1.4"
when "10.6" then "3.2.6" when "10.6" then "3.2.6"
when "10.7" then "4.6.3" when "10.7" then "4.6.3"
when "10.8" then "5.0" when "10.8" then "5.0"
when "10.9" then "5.0.1" when "10.9" then "5.0.1"
else else
# Default to newest known version of Xcode for unreleased OSX versions. # Default to newest known version of Xcode for unreleased OSX versions.
if MacOS.version > 10.9 if MacOS.version > 10.9
"5.0.1" "5.0.1"
else else
raise "Mac OS X '#{MacOS.version}' is invalid" 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 end
end
def outdated? module CLT
version < latest_version extend self
end
def without_clt? STANDALONE_PKG_ID = "com.apple.pkg.DeveloperToolsCLILeo"
installed? && version >= "4.3" && !MacOS::CLT.installed? FROM_XCODE_PKG_ID = "com.apple.pkg.DeveloperToolsCLI"
end STANDALONE_PKG_PATH = Pathname.new("/Library/Developer/CommandLineTools")
def prefix # True if:
@prefix ||= begin # - Xcode < 4.3 is installed. The tools are found under /usr.
path = Pathname.new(folder) # - The "Command Line Tools" package has been installed
if path.absolute? and File.executable? "#{path}/usr/bin/make" # For OS X < 10.9, the tools are found under /usr. For 10.9,
path # they are found under /Library/Developer/CommandLineTools.
elsif File.executable? '/Developer/usr/bin/make' def installed?
# we do this to support cowboys who insist on installing mavericks_dev_tools? || usr_dev_tools?
# 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
end
# Ask Spotlight where Xcode is. If the user didn't install the def mavericks_dev_tools?
# helper tools and installed Xcode in a non-conventional place, this MacOS.dev_tools_path == Pathname("#{STANDALONE_PKG_PATH}/usr/bin") &&
# is our only option. See: http://superuser.com/questions/390757 File.directory?("#{STANDALONE_PKG_PATH}/usr/include")
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
end
def provides_autotools? def usr_dev_tools?
version.to_f < 4.3 MacOS.dev_tools_path == Pathname("/usr/bin") && File.directory?("/usr/include")
end end
def provides_gcc? def latest_version?
version.to_f < 4.3 `/usr/bin/clang --version` =~ %r{clang-(\d+)\.(\d+)\.(\d+)}
end $1.to_i >= 425 and $3.to_i >= 28
end
def default_prefix? def outdated?
if version.to_f < 4.3 !latest_version?
%r{^/Developer} === prefix end
else
%r{^/Applications/Xcode.app} === prefix # Version string (a pretty damn long one) of the CLT package.
end # Note, that different ways to install the CLTs lead to different
end # version numbers.
end def version
@version ||= detect_version
module MacOS::CLT extend self end
STANDALONE_PKG_ID = "com.apple.pkg.DeveloperToolsCLILeo"
FROM_XCODE_PKG_ID = "com.apple.pkg.DeveloperToolsCLI" def detect_version
STANDALONE_PKG_PATH = Pathname.new("/Library/Developer/CommandLineTools") [STANDALONE_PKG_ID, FROM_XCODE_PKG_ID].find do |id|
version = MacOS.pkgutil_info(id)[/version: (.+)$/, 1]
# True if: return version if version
# - Xcode < 4.3 is installed. The tools are found under /usr. end
# - The "Command Line Tools" package has been installed end
# 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
end end
end end
end end

View File

@ -1,131 +1,139 @@
module MacOS::XQuartz extend self module OS
FORGE_BUNDLE_ID = "org.macosforge.xquartz.X11" module Mac
APPLE_BUNDLE_ID = "org.x.X11" module XQuartz
FORGE_PKG_ID = "org.macosforge.xquartz.pkg" extend self
PKGINFO_VERSION_MAP = { FORGE_BUNDLE_ID = "org.macosforge.xquartz.X11"
"2.6.34" => "2.6.3", APPLE_BUNDLE_ID = "org.x.X11"
"2.7.4" => "2.7.0", FORGE_PKG_ID = "org.macosforge.xquartz.pkg"
"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
# This returns the version number of XQuartz, not of the upstream X.org. PKGINFO_VERSION_MAP = {
# The X11.app distributed by Apple is also XQuartz, and therefore covered "2.6.34" => "2.6.3",
# by this method. "2.7.4" => "2.7.0",
def version "2.7.14" => "2.7.1",
@version ||= detect_version "2.7.28" => "2.7.2",
end "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 # This returns the version number of XQuartz, not of the upstream X.org.
if (path = bundle_path) && path.exist? && (version = version_from_mdls(path)) # The X11.app distributed by Apple is also XQuartz, and therefore covered
version # by this method.
elsif prefix.to_s == "/usr/X11" def version
guess_system_version @version ||= detect_version
else end
version_from_pkgutil
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
end
def latest_version module X11
"2.7.4" extend self
end
def bundle_path def prefix
MacOS.app_with_bundle_id(FORGE_BUNDLE_ID) || MacOS.app_with_bundle_id(APPLE_BUNDLE_ID) MacOS::XQuartz.prefix
end end
def version_from_mdls(path) def installed?
version = `mdls -raw -nullMarker "" -name kMDItemVersion "#{path}" 2>/dev/null`.strip MacOS::XQuartz.installed?
version unless version.empty? end
end
# The XQuartz that Apple shipped in OS X through 10.7 does not have a # If XQuartz and/or the CLT are installed, headers will be found under
# pkg-util entry, so if Spotlight indexing is disabled we must make an # /opt/X11/include or /usr/X11/include. For Xcode-only systems, they are
# educated guess as to what version is installed. # found in the SDK, so we use sdk_path for both the headers and libraries.
def guess_system_version # Confusingly, executables (e.g. config scripts) are only found under
case MacOS.version # /opt/X11/bin or /usr/X11/bin in all cases.
when '10.5' then '2.1.6' def bin
when '10.6' then '2.3.6' Pathname.new("#{prefix}/bin")
when '10.7' then '2.6.3' end
else 'dunno'
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
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 end