Module: OS::Mac::Xcode Private

Defined in:
Library/Homebrew/os/mac/xcode.rb,
Library/Homebrew/os/linux.rb

Overview

This module is part of a private API. You should avoid using this module if possible, as it may be removed or be changed in the future.

Helper module for querying Xcode information.

Constant Summary collapse

DEFAULT_BUNDLE_PATH =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Pathname.new("/Applications/Xcode.app").freeze
BUNDLE_ID =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

"com.apple.dt.Xcode"
OLD_BUNDLE_ID =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

"com.apple.Xcode"

Class Method Summary collapse

Class Method Details

.below_minimum_version?Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns:

  • (Boolean)

52
53
54
55
56
# File 'Library/Homebrew/os/mac/xcode.rb', line 52

def below_minimum_version?
  return false unless installed?

  version < minimum_version
end

.bundle_pathObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.


99
100
101
102
103
104
105
106
107
# File 'Library/Homebrew/os/mac/xcode.rb', line 99

def bundle_path
  # Use the default location if it exists.
  return DEFAULT_BUNDLE_PATH if DEFAULT_BUNDLE_PATH.exist?

  # 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: https://superuser.com/questions/390757
  MacOS.app_with_bundle_id(BUNDLE_ID, OLD_BUNDLE_ID)
end

.default_prefix?Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns:

  • (Boolean)

201
202
203
# File 'Library/Homebrew/os/mac/xcode.rb', line 201

def default_prefix?
  prefix.to_s == "/Applications/Xcode.app/Contents/Developer"
end

.detect_versionObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.


149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
# File 'Library/Homebrew/os/mac/xcode.rb', line 149

def detect_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 if !MacOS::Xcode.installed? && !MacOS::CLT.installed?

  %W[
    #{prefix}/usr/bin/xcodebuild
    #{which("xcodebuild")}
  ].uniq.each do |xcodebuild_path|
    next unless File.executable? xcodebuild_path

    xcodebuild_output = Utils.popen_read(xcodebuild_path, "-version")
    next unless $CHILD_STATUS.success?

    xcode_version = xcodebuild_output[/Xcode (\d+(\.\d+)*)/, 1]
    return xcode_version if xcode_version

    # Xcode 2.x's xcodebuild has a different version string
    case xcodebuild_output[/DevToolsCore-(\d+\.\d)/, 1]
    when "798.0" then return "2.5"
    when "515.0" then return "2.0"
    end
  end

  detect_version_from_clang_version
end

.detect_version_from_clang_versionObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.


176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
# File 'Library/Homebrew/os/mac/xcode.rb', line 176

def detect_version_from_clang_version
  return "dunno" if DevelopmentTools.clang_version.null?

  # This logic provides a fake Xcode version based on the
  # installed CLT version. This is useful as they are packaged
  # simultaneously so workarounds need to apply to both based on their
  # comparable version.
  latest_stable = "11.5"
  case (DevelopmentTools.clang_version.to_f * 10).to_i
  when 120     then "12.0"
  when 110     then latest_stable
  when 100     then "10.3"
  when 91      then "9.4"
  when 90      then "9.2"
  when 81      then "8.3"
  when 80      then "8.0"
  when 73      then "7.3"
  when 70      then "7.0"
  when 61      then "6.1"
  when 60      then "6.0"
  when 0       then "dunno"
  else              latest_stable
  end
end

.installed?Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns:

  • (Boolean)

109
110
111
# File 'Library/Homebrew/os/mac/xcode.rb', line 109

def installed?
  !prefix.nil?
end

.latest_sdk_version?Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns:

  • (Boolean)

58
59
60
# File 'Library/Homebrew/os/mac/xcode.rb', line 58

def latest_sdk_version?
  OS::Mac.version >= OS::Mac.latest_sdk_version
end

.latest_versionObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Bump these when a new version is available from the App Store and our CI systems have been updated. This may be a beta version for a beta macOS.


18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'Library/Homebrew/os/mac/xcode.rb', line 18

def latest_version
  latest_stable = "11.5"
  case MacOS.version
  when "11.0"  then "12.0"
  when "10.15" then latest_stable
  when "10.14" then "11.3.1"
  when "10.13" then "10.1"
  when "10.12" then "9.2"
  when "10.11" then "8.2.1"
  when "10.10" then "7.2.1"
  when "10.9"  then "6.2"
  else
    raise "macOS '#{MacOS.version}' is invalid" unless OS::Mac.prerelease?

    # Default to newest known version of Xcode for unreleased macOS versions.
    latest_stable
  end
end

.minimum_versionObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Bump these if things are badly broken (e.g. no SDK for this macOS) without this. Generally this will be the first Xcode release on that macOS version (which may initially be a beta if that version of macOS is also in beta).


41
42
43
44
45
46
47
48
49
50
# File 'Library/Homebrew/os/mac/xcode.rb', line 41

def minimum_version
  case MacOS.version
  when "11.0"  then "12.0"
  when "10.15" then "11.0"
  when "10.14" then "10.2"
  when "10.13" then "9.0"
  when "10.12" then "8.0"
  else "2.0"
  end
end

.needs_clt_installed?Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns:

  • (Boolean)

62
63
64
65
66
# File 'Library/Homebrew/os/mac/xcode.rb', line 62

def needs_clt_installed?
  return false if latest_sdk_version?

  without_clt?
end

.outdated?Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns:

  • (Boolean)

68
69
70
71
72
# File 'Library/Homebrew/os/mac/xcode.rb', line 68

def outdated?
  return false unless installed?

  version < latest_version
end

.prefixObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns a Pathname object corresponding to Xcode.app's Developer directory or nil if Xcode.app is not installed


80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'Library/Homebrew/os/mac/xcode.rb', line 80

def prefix
  @prefix ||=
    begin
      dir = MacOS.active_developer_dir

      if dir.empty? || dir == CLT::PKG_PATH || !File.directory?(dir)
        path = bundle_path
        path/"Contents/Developer" if path
      else
        # Use cleanpath to avoid pathological trailing slash
        Pathname.new(dir).cleanpath
      end
    end
end

.sdk(v = nil) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.


117
118
119
# File 'Library/Homebrew/os/mac/xcode.rb', line 117

def sdk(v = nil)
  sdk_locator.sdk_if_applicable(v)
end

.sdk_locatorObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.


113
114
115
# File 'Library/Homebrew/os/mac/xcode.rb', line 113

def sdk_locator
  @sdk_locator ||= XcodeSDKLocator.new
end

.sdk_path(v = nil) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.


121
122
123
# File 'Library/Homebrew/os/mac/xcode.rb', line 121

def sdk_path(v = nil)
  sdk(v)&.path
end

.toolchain_pathObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.


95
96
97
# File 'Library/Homebrew/os/mac/xcode.rb', line 95

def toolchain_path
  Pathname.new("#{prefix}/Toolchains/XcodeDefault.xctoolchain")
end

.update_instructionsObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.


125
126
127
128
129
130
131
132
133
134
135
136
# File 'Library/Homebrew/os/mac/xcode.rb', line 125

def update_instructions
  if OS::Mac.prerelease?
    <<~EOS
      Xcode can be updated from:
        #{Formatter.url("https://developer.apple.com/download/more/")}
    EOS
  else
    <<~EOS
      Xcode can be updated from the App Store.
    EOS
  end
end

.versionObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.


68
69
70
# File 'Library/Homebrew/os/linux.rb', line 68

def version
  Version::NULL
end

.without_clt?Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns:

  • (Boolean)

74
75
76
# File 'Library/Homebrew/os/mac/xcode.rb', line 74

def without_clt?
  !MacOS::CLT.installed?
end