Class: DevelopmentTools

Inherits:
Object show all
Extended by:
Utils::Output::Mixin
Defined in:
development_tools.rb

Overview

Helper class for gathering information about development tools.

Class Method Summary collapse

Methods included from Utils::Output::Mixin

issue_reporting_message, odebug, odeprecated, odie, odisabled, ofail, oh1, oh1_title, ohai, ohai_title, onoe, opoo, opoo_once, opoo_outside_github_actions, opoo_without_github_actions_annotation, pretty_cannot_install, pretty_deprecated, pretty_disabled, pretty_duration, pretty_install_status, pretty_installed, pretty_removed, pretty_uninstalled, pretty_unmarked, pretty_upgradable, pretty_warning

Class Method Details

.build_system_info ⇒ Hash{String => String, nil}

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Returns:



213
214
215
216
217
218
219
# File 'development_tools.rb', line 213

def build_system_info
  {
    "os"         => HOMEBREW_SYSTEM,
    "os_version" => OS_VERSION,
    "cpu_family" => Hardware::CPU.family.to_s,
  }
end

.ca_file_substitution_required? ⇒ Boolean

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Returns:

  • (Boolean)


198
199
200
201
# File 'development_tools.rb', line 198

def ca_file_substitution_required?
  ENV["HOMEBREW_FORCE_BREWED_CA_CERTIFICATES"].present? &&
    !(HOMEBREW_PREFIX/"etc/ca-certificates/cert.pem").exist?
end

.clang_build_version ⇒ Version

Get the Clang build version.

Returns:



97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'development_tools.rb', line 97

def clang_build_version
  if Homebrew::SimulateSystem.simulating? &&
     Homebrew::SimulateSystem.simulating_or_running_on_macos? &&
     MacOSVersion::SYMBOLS.key?(Homebrew::SimulateSystem.current_os)
    require "os/mac/xcode"
    clang_version = OS::Mac::CLT.latest_clang_version(
      macos: MacOSVersion.from_symbol(Homebrew::SimulateSystem.current_os),
      arm64: Homebrew::SimulateSystem.current_arch == :arm,
    )
    return Version.new(clang_version.split(".", 2).fetch(0))
  end

  @clang_build_version ||= T.let(
    if (build_version = clang_version_output&.[](%r{clang(?:-| version [^ ]+ \(tags/RELEASE_)(\d{2,})}, 1))
      Version.new(build_version)
    else
      Version::NULL
    end, T.nilable(Version)
  )
end

.clang_version ⇒ Version

Get the Clang version.

Returns:



83
84
85
86
87
88
89
90
91
# File 'development_tools.rb', line 83

def clang_version
  @clang_version ||= T.let(
    if (build_version = clang_version_output&.[](/(?:clang|LLVM) version (\d+\.\d(?:\.\d)?)/, 1))
      Version.new(build_version)
    else
      Version::NULL
    end, T.nilable(Version)
  )
end

.clang_version_output ⇒ String?

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Returns:



71
72
73
74
75
76
77
# File 'development_tools.rb', line 71

def clang_version_output
  @clang_version_output ||= T.let(
    if (path = locate("clang"))
      Utils.popen_read_text(path, "--version", err: :err)
    end, T.nilable(String)
  )
end

.clear_version_cache ⇒ void

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

This method returns an undefined value.



171
172
173
174
175
# File 'development_tools.rb', line 171

def clear_version_cache
  @clang_version_output = T.let(nil, T.nilable(String))
  @clang_version = @clang_build_version = @llvm_clang_version = T.let(nil, T.nilable(Version))
  @gcc_version = T.let({}, T.nilable(T::Hash[String, Version]))
end

.curl_handles_most_https_certificates? ⇒ Boolean

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Returns:

  • (Boolean)


193
194
195
# File 'development_tools.rb', line 193

def curl_handles_most_https_certificates?
  true
end

.curl_substitution_required? ⇒ Boolean

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Returns:

  • (Boolean)


204
205
206
207
208
209
210
# File 'development_tools.rb', line 204

def curl_substitution_required?
  return false if curl_handles_most_https_certificates? || HOMEBREW_BREWED_CURL_PATH.exist?

  require "utils/curl"

  Utils::Curl.curl_version < Version.new(ENV.fetch("HOMEBREW_MINIMUM_CURL_VERSION"))
end

.custom_installation_instructions ⇒ String

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Returns:



45
46
47
# File 'development_tools.rb', line 45

def custom_installation_instructions
  installation_instructions
end

.default_compiler ⇒ Symbol

Get the default C compiler.

Returns:



61
62
63
# File 'development_tools.rb', line 61

def default_compiler
  :clang
end

.gcc_version(cc = host_gcc_path.to_s) ⇒ Version

Get the GCC version.

Parameters:

  • cc (String) (defaults to: host_gcc_path.to_s)

Returns:



154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
# File 'development_tools.rb', line 154

def gcc_version(cc = host_gcc_path.to_s)
  (@gcc_version ||= T.let({}, T.nilable(T::Hash[String, Version]))).fetch(cc) do
    path = HOMEBREW_PREFIX/"opt/#{CompilerSelector.preferred_gcc}/bin"/cc
    path = locate(cc) unless path.exist?
    version = if path &&
                 (build_version = Utils.popen_read_text(path, "--version", err: :err)[
                   /gcc(?:(?:-\d+(?:\.\d)?)? \(.+\))? (\d+\.\d\.\d)/, 1
                 ])
      Version.new(build_version)
    else
      Version::NULL
    end
    @gcc_version[cc] = version
  end
end

.host_gcc_path ⇒ Pathname

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Returns:



146
147
148
# File 'development_tools.rb', line 146

def host_gcc_path
  Pathname.new("/usr/bin/gcc")
end

.insecure_download_warning(resource) ⇒ String

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Parameters:

Returns:



50
51
52
53
54
55
# File 'development_tools.rb', line 50

def insecure_download_warning(resource)
  package = curl_handles_most_https_certificates? ? "ca-certificates" : "curl"
  "Using `--insecure` with curl to download #{resource} because we need it to run " \
    "`brew install #{package}` in order to download securely from now on. " \
    "Checksums will still be verified."
end

.installation_instructions ⇒ String

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Returns:



40
41
42
# File 'development_tools.rb', line 40

def installation_instructions
  "Install Clang or run `brew install gcc`."
end

.installed? ⇒ Boolean

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Returns:

  • (Boolean)


35
36
37
# File 'development_tools.rb', line 35

def installed?
  !!(locate("clang") || locate("gcc"))
end

.ld64_version ⇒ Version

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Returns:



66
67
68
# File 'development_tools.rb', line 66

def ld64_version
  Version::NULL
end

.llvm_clang_build_version ⇒ Version

Deprecated.

Query the required LLVM compiler with --version instead.

Get the LLVM Clang build version.

Returns:



123
124
125
126
127
# File 'development_tools.rb', line 123

def llvm_clang_build_version
  odeprecated "DevelopmentTools.llvm_clang_build_version", "the required LLVM compiler's `--version` output"

  llvm_clang_version
end

.llvm_clang_version ⇒ Version

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Returns:



131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'development_tools.rb', line 131

def llvm_clang_version
  @llvm_clang_version ||= T.let(begin
    path = Formula["llvm"].opt_prefix/"bin/clang"
    if path.executable? &&
       (build_version = Utils.popen_read_text(path, "--version", err: :err)[/clang version (\d+\.\d\.\d)/, 1])
      Version.new(build_version)
    else
      Version::NULL
    end
  rescue FormulaUnavailableError
    Version::NULL
  end, T.nilable(Version))
end

.locate(tool) ⇒ Pathname?

Locate a development tool.

Parameters:

Returns:



20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'development_tools.rb', line 20

def locate(tool)
  # Don't call tools (cc, make, strip, etc.) directly!
  # Give the name of the binary you look for as a string to this method
  # in order to get the full path back as a Pathname.
  (@locate ||= T.let({}, T.nilable(T::Hash[T.any(String, Symbol), T.untyped]))).fetch(tool) do |key|
    @locate[key] = if File.executable?(path = "/usr/bin/#{tool}")
      Pathname.new path
    # Homebrew GCCs most frequently; much faster to check this before xcrun
    elsif (path = HOMEBREW_PREFIX/"bin/#{tool}").executable?
      path
    end
  end
end

.needs_build_formulae? ⇒ Boolean

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Returns:

  • (Boolean)


178
179
180
# File 'development_tools.rb', line 178

def needs_build_formulae?
  needs_libc_formula? || needs_compiler_formula?
end

.needs_compiler_formula? ⇒ Boolean

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Returns:

  • (Boolean)


188
189
190
# File 'development_tools.rb', line 188

def needs_compiler_formula?
  false
end

.needs_libc_formula? ⇒ Boolean

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Returns:

  • (Boolean)


183
184
185
# File 'development_tools.rb', line 183

def needs_libc_formula?
  false
end