2020-10-10 14:16:11 +02:00
|
|
|
# typed: true
|
2019-04-19 15:38:03 +09:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2015-12-04 13:58:22 -08:00
|
|
|
require "os/mac/version"
|
|
|
|
|
|
|
|
module OS
|
|
|
|
module Mac
|
2020-08-25 00:33:34 +02:00
|
|
|
# Class representing a macOS SDK.
|
|
|
|
#
|
|
|
|
# @api private
|
2015-12-04 13:58:22 -08:00
|
|
|
class SDK
|
2020-04-07 16:43:32 +01:00
|
|
|
attr_reader :version, :path, :source
|
2015-12-04 13:58:22 -08:00
|
|
|
|
2020-04-07 16:43:32 +01:00
|
|
|
def initialize(version, path, source)
|
2020-10-05 14:46:43 +02:00
|
|
|
@version = version
|
2015-12-04 13:58:22 -08:00
|
|
|
@path = Pathname.new(path)
|
2020-04-07 16:43:32 +01:00
|
|
|
@source = source
|
2015-12-04 13:58:22 -08:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2020-08-25 00:33:34 +02:00
|
|
|
# Base class for SDK locators.
|
|
|
|
#
|
|
|
|
# @api private
|
2018-06-12 14:55:31 -07:00
|
|
|
class BaseSDKLocator
|
2015-12-04 13:58:22 -08:00
|
|
|
class NoSDKError < StandardError; end
|
|
|
|
|
|
|
|
def sdk_for(v)
|
|
|
|
path = sdk_paths[v]
|
|
|
|
raise NoSDKError if path.nil?
|
|
|
|
|
2020-04-07 16:43:32 +01:00
|
|
|
SDK.new v, path, source
|
2015-12-04 13:58:22 -08:00
|
|
|
end
|
|
|
|
|
|
|
|
def latest_sdk
|
|
|
|
return if sdk_paths.empty?
|
|
|
|
|
2020-10-12 04:35:53 +02:00
|
|
|
v, path = sdk_paths.max { |(v1, _), (v2, _)| v1 <=> v2 }
|
2020-04-07 16:43:32 +01:00
|
|
|
SDK.new v, path, source
|
2015-12-04 13:58:22 -08:00
|
|
|
end
|
|
|
|
|
2020-07-01 16:02:29 +01:00
|
|
|
def all_sdks
|
|
|
|
sdk_paths.map { |v, p| SDK.new v, p, source }
|
|
|
|
end
|
|
|
|
|
2018-07-26 17:57:11 -07:00
|
|
|
def sdk_if_applicable(v = nil)
|
2018-07-27 15:44:22 -07:00
|
|
|
sdk = begin
|
2020-11-27 20:18:56 +00:00
|
|
|
if v.blank?
|
|
|
|
sdk_for OS::Mac.sdk_version
|
2018-07-26 17:57:11 -07:00
|
|
|
else
|
|
|
|
sdk_for v
|
|
|
|
end
|
2020-08-25 00:33:34 +02:00
|
|
|
rescue NoSDKError
|
2018-07-27 15:44:22 -07:00
|
|
|
latest_sdk
|
2018-07-26 17:57:11 -07:00
|
|
|
end
|
2020-11-30 12:58:38 +00:00
|
|
|
return if sdk.blank?
|
|
|
|
|
2020-11-27 16:23:10 -08:00
|
|
|
# Accept an SDK for another OS version if it shares a major version
|
|
|
|
# with the current OS - for example, the 11.0 SDK on 11.1,
|
|
|
|
# or vice versa.
|
|
|
|
# Note that this only applies on macOS 11
|
|
|
|
# or greater, given the way the versioning has changed.
|
|
|
|
# This shortcuts the below check, since we *do* accept an older version
|
|
|
|
# on macOS 11 or greater if the major version matches.
|
2020-11-30 12:58:38 +00:00
|
|
|
return sdk if OS::Mac.version >= :big_sur && sdk.version.major == OS::Mac.version.major
|
2020-11-27 16:23:10 -08:00
|
|
|
|
|
|
|
# On OSs lower than 11, or where the major versions don't match,
|
|
|
|
# only return an SDK older than the OS version if it was specifically requested
|
2020-11-30 12:58:38 +00:00
|
|
|
return if v.blank? && sdk.version < OS::Mac.version
|
2018-09-17 02:45:00 +02:00
|
|
|
|
2018-07-27 15:44:22 -07:00
|
|
|
sdk
|
2018-07-26 17:57:11 -07:00
|
|
|
end
|
|
|
|
|
2020-04-07 16:43:32 +01:00
|
|
|
def source
|
|
|
|
nil
|
|
|
|
end
|
|
|
|
|
2020-07-01 16:02:29 +01:00
|
|
|
private
|
2018-07-26 17:57:11 -07:00
|
|
|
|
2018-06-12 14:55:31 -07:00
|
|
|
def sdk_prefix
|
|
|
|
""
|
|
|
|
end
|
|
|
|
|
2015-12-04 13:58:22 -08:00
|
|
|
def sdk_paths
|
|
|
|
@sdk_paths ||= begin
|
|
|
|
# Bail out if there is no SDK prefix at all
|
2020-11-09 20:09:16 +11:00
|
|
|
if File.directory? sdk_prefix
|
2015-12-04 13:58:22 -08:00
|
|
|
paths = {}
|
|
|
|
|
|
|
|
Dir[File.join(sdk_prefix, "MacOSX*.sdk")].each do |sdk_path|
|
2016-07-13 16:19:51 +08:00
|
|
|
version = sdk_path[/MacOSX(\d+\.\d+)u?\.sdk$/, 1]
|
2020-11-27 20:18:56 +00:00
|
|
|
paths[OS::Mac::Version.new(version)] = sdk_path if version.present?
|
2015-12-04 13:58:22 -08:00
|
|
|
end
|
|
|
|
|
2020-12-20 14:02:48 +00:00
|
|
|
# Use unversioned SDK path on Big Sur to avoid issues such as:
|
|
|
|
# https://github.com/Homebrew/homebrew-core/issues/67075
|
|
|
|
if OS::Mac.version >= :big_sur
|
|
|
|
sdk_path = File.join(sdk_prefix, "MacOSX.sdk")
|
|
|
|
version = OS::Mac.full_version
|
|
|
|
paths[version] = sdk_path if File.directory?(sdk_path)
|
|
|
|
end
|
|
|
|
|
2015-12-04 13:58:22 -08:00
|
|
|
paths
|
2020-11-09 20:09:16 +11:00
|
|
|
else
|
|
|
|
{}
|
2015-12-04 13:58:22 -08:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2020-08-25 00:33:34 +02:00
|
|
|
private_constant :BaseSDKLocator
|
2018-06-12 14:55:31 -07:00
|
|
|
|
2020-08-25 00:33:34 +02:00
|
|
|
# Helper class for locating the Xcode SDK.
|
|
|
|
#
|
|
|
|
# @api private
|
2018-06-12 14:55:31 -07:00
|
|
|
class XcodeSDKLocator < BaseSDKLocator
|
2020-10-20 12:03:48 +02:00
|
|
|
extend T::Sig
|
|
|
|
|
|
|
|
sig { returns(Symbol) }
|
2020-04-07 16:43:32 +01:00
|
|
|
def source
|
|
|
|
:xcode
|
|
|
|
end
|
|
|
|
|
2020-07-01 16:02:29 +01:00
|
|
|
private
|
2018-07-26 17:57:11 -07:00
|
|
|
|
2018-06-12 14:55:31 -07:00
|
|
|
def sdk_prefix
|
|
|
|
@sdk_prefix ||= begin
|
|
|
|
# Xcode.prefix is pretty smart, so let's look inside to find the sdk
|
|
|
|
sdk_prefix = "#{Xcode.prefix}/Platforms/MacOSX.platform/Developer/SDKs"
|
|
|
|
# Finally query Xcode itself (this is slow, so check it last)
|
2018-07-27 15:44:22 -07:00
|
|
|
sdk_platform_path = Utils.popen_read(DevelopmentTools.locate("xcrun"), "--show-sdk-platform-path").chomp
|
|
|
|
sdk_prefix = File.join(sdk_platform_path, "Developer", "SDKs") unless File.directory? sdk_prefix
|
2018-06-12 14:55:31 -07:00
|
|
|
|
|
|
|
sdk_prefix
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2020-08-25 00:33:34 +02:00
|
|
|
# Helper class for locating the macOS Command Line Tools SDK.
|
|
|
|
#
|
|
|
|
# @api private
|
2018-06-12 14:55:31 -07:00
|
|
|
class CLTSDKLocator < BaseSDKLocator
|
2020-10-20 12:03:48 +02:00
|
|
|
extend T::Sig
|
|
|
|
|
|
|
|
sig { returns(Symbol) }
|
2020-04-07 16:43:32 +01:00
|
|
|
def source
|
|
|
|
:clt
|
|
|
|
end
|
|
|
|
|
2020-07-01 16:02:29 +01:00
|
|
|
private
|
2018-07-26 17:57:11 -07:00
|
|
|
|
2018-06-12 14:55:31 -07:00
|
|
|
# While CLT SDKs existed prior to Xcode 10, those packages also
|
|
|
|
# installed a traditional Unix-style header layout and we prefer
|
2020-11-05 17:17:03 -05:00
|
|
|
# using that.
|
2018-06-12 14:55:31 -07:00
|
|
|
# As of Xcode 10, the Unix-style headers are installed via a
|
|
|
|
# separate package, so we can't rely on their being present.
|
|
|
|
# This will only look up SDKs on Xcode 10 or newer, and still
|
|
|
|
# return nil SDKs for Xcode 9 and older.
|
|
|
|
def sdk_prefix
|
|
|
|
@sdk_prefix ||= begin
|
2020-11-09 20:09:16 +11:00
|
|
|
if CLT.provides_sdk?
|
2018-06-12 14:55:31 -07:00
|
|
|
"#{CLT::PKG_PATH}/SDKs"
|
2020-11-09 20:09:16 +11:00
|
|
|
else
|
|
|
|
""
|
2018-06-12 14:55:31 -07:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2015-12-04 13:58:22 -08:00
|
|
|
end
|
|
|
|
end
|