| 
									
										
										
										
											2024-07-05 16:37:34 +01:00
										 |  |  | # typed: strict | 
					
						
							| 
									
										
										
										
											2019-04-19 15:38:03 +09:00
										 |  |  | # frozen_string_literal: true | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-29 15:12:53 -07:00
										 |  |  | require "version" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-06 01:00:39 +01:00
										 |  |  | # Helper class for gathering information about development tools. | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | # @api public | 
					
						
							| 
									
										
										
										
											2016-04-25 18:01:03 +01:00
										 |  |  | class DevelopmentTools | 
					
						
							|  |  |  |   class << self | 
					
						
							| 
									
										
										
										
											2024-03-06 01:00:39 +01:00
										 |  |  |     # Locate a development tool. | 
					
						
							|  |  |  |     # | 
					
						
							|  |  |  |     # @api public | 
					
						
							| 
									
										
										
										
											2023-08-04 11:26:30 +08:00
										 |  |  |     sig { params(tool: T.any(String, Symbol)).returns(T.nilable(Pathname)) } | 
					
						
							| 
									
										
										
										
											2016-04-25 18:01:03 +01:00
										 |  |  |     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. | 
					
						
							| 
									
										
										
										
											2024-07-05 21:14:03 +01:00
										 |  |  |       (@locate ||= T.let({}, T.nilable(T::Hash[T.any(String, Symbol), T.untyped]))).fetch(tool) do |key| | 
					
						
							| 
									
										
										
										
											2024-04-08 19:23:33 +01:00
										 |  |  |         @locate[key] = if File.executable?((path = "/usr/bin/#{tool}")) | 
					
						
							| 
									
										
										
										
											2016-04-25 18:01:03 +01:00
										 |  |  |           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 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-29 15:12:53 -07:00
										 |  |  |     sig { returns(T::Boolean) } | 
					
						
							| 
									
										
										
										
											2016-04-25 18:01:03 +01:00
										 |  |  |     def installed? | 
					
						
							| 
									
										
										
										
											2021-09-29 15:12:53 -07:00
										 |  |  |       locate("clang").present? || locate("gcc").present? | 
					
						
							| 
									
										
										
										
											2016-04-25 18:01:03 +01:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-29 15:12:53 -07:00
										 |  |  |     sig { returns(String) } | 
					
						
							| 
									
										
										
										
											2016-07-16 21:01:22 +01:00
										 |  |  |     def installation_instructions | 
					
						
							| 
									
										
										
										
											2019-04-05 12:24:10 -04:00
										 |  |  |       "Install Clang or run `brew install gcc`." | 
					
						
							| 
									
										
										
										
											2016-07-16 21:01:22 +01:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-29 15:12:53 -07:00
										 |  |  |     sig { returns(String) } | 
					
						
							|  |  |  |     def custom_installation_instructions | 
					
						
							|  |  |  |       installation_instructions | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-04 22:24:57 -04:00
										 |  |  |     sig { params(resource: String).returns(String) } | 
					
						
							|  |  |  |     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 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-06 01:00:39 +01:00
										 |  |  |     # Get the default C compiler. | 
					
						
							|  |  |  |     # | 
					
						
							|  |  |  |     # @api public | 
					
						
							| 
									
										
										
										
											2021-09-29 15:12:53 -07:00
										 |  |  |     sig { returns(Symbol) } | 
					
						
							| 
									
										
										
										
											2016-04-25 18:01:03 +01:00
										 |  |  |     def default_compiler | 
					
						
							| 
									
										
										
										
											2016-12-30 20:20:13 +00:00
										 |  |  |       :clang | 
					
						
							| 
									
										
										
										
											2016-04-25 18:01:03 +01:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-06 01:00:39 +01:00
										 |  |  |     # Get the Clang version. | 
					
						
							|  |  |  |     # | 
					
						
							|  |  |  |     # @api public | 
					
						
							| 
									
										
										
										
											2021-09-29 15:12:53 -07:00
										 |  |  |     sig { returns(Version) } | 
					
						
							| 
									
										
										
										
											2016-04-25 18:01:03 +01:00
										 |  |  |     def clang_version | 
					
						
							| 
									
										
										
										
											2024-07-05 16:37:34 +01:00
										 |  |  |       @clang_version ||= T.let( | 
					
						
							| 
									
										
										
										
											2024-07-05 21:14:03 +01:00
										 |  |  |         if (path = locate("clang")) && | 
					
						
							|  |  |  |            (build_version = `#{path} --version`[/(?:clang|LLVM) version (\d+\.\d(?:\.\d)?)/, 1]) | 
					
						
							|  |  |  |           Version.new(build_version) | 
					
						
							| 
									
										
										
										
											2024-07-05 16:37:34 +01:00
										 |  |  |         else | 
					
						
							|  |  |  |           Version::NULL | 
					
						
							|  |  |  |         end, T.nilable(Version) | 
					
						
							|  |  |  |       ) | 
					
						
							| 
									
										
										
										
											2016-04-25 18:01:03 +01:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-06 01:00:39 +01:00
										 |  |  |     # Get the Clang build version. | 
					
						
							|  |  |  |     # | 
					
						
							|  |  |  |     # @api public | 
					
						
							| 
									
										
										
										
											2021-09-29 15:12:53 -07:00
										 |  |  |     sig { returns(Version) } | 
					
						
							| 
									
										
										
										
											2016-04-25 18:01:03 +01:00
										 |  |  |     def clang_build_version | 
					
						
							| 
									
										
										
										
											2024-07-05 16:37:34 +01:00
										 |  |  |       @clang_build_version ||= T.let( | 
					
						
							|  |  |  |         if (path = locate("clang")) && | 
					
						
							|  |  |  |           (build_version = `#{path} --version`[%r{clang(-| version [^ ]+ \(tags/RELEASE_)(\d{2,})}, 2]) | 
					
						
							|  |  |  |           Version.new(build_version) | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |           Version::NULL | 
					
						
							|  |  |  |         end, T.nilable(Version) | 
					
						
							|  |  |  |       ) | 
					
						
							| 
									
										
										
										
											2016-04-25 18:01:03 +01:00
										 |  |  |     end | 
					
						
							| 
									
										
										
										
											2016-05-10 08:19:48 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-06 01:00:39 +01:00
										 |  |  |     # Get the LLVM Clang build version. | 
					
						
							|  |  |  |     # | 
					
						
							|  |  |  |     # @api public | 
					
						
							| 
									
										
										
										
											2021-09-29 15:12:53 -07:00
										 |  |  |     sig { returns(Version) } | 
					
						
							| 
									
										
										
										
											2016-09-24 23:56:54 -04:00
										 |  |  |     def llvm_clang_build_version | 
					
						
							| 
									
										
										
										
											2024-07-05 16:37:34 +01:00
										 |  |  |       @llvm_clang_build_version ||= T.let(begin | 
					
						
							| 
									
										
										
										
											2016-09-24 23:56:54 -04:00
										 |  |  |         path = Formulary.factory("llvm").opt_prefix/"bin/clang" | 
					
						
							| 
									
										
										
										
											2024-07-05 21:14:03 +01:00
										 |  |  |         if path.executable? && (build_version = `#{path} --version`[/clang version (\d+\.\d\.\d)/, 1]) | 
					
						
							|  |  |  |           Version.new(build_version) | 
					
						
							| 
									
										
										
										
											2016-11-21 08:49:29 +00:00
										 |  |  |         else | 
					
						
							|  |  |  |           Version::NULL | 
					
						
							|  |  |  |         end | 
					
						
							| 
									
										
										
										
											2024-07-05 16:37:34 +01:00
										 |  |  |       end, T.nilable(Version)) | 
					
						
							| 
									
										
										
										
											2016-09-24 23:56:54 -04:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-22 21:05:48 +02:00
										 |  |  |     # Get the GCC version. | 
					
						
							|  |  |  |     # | 
					
						
							|  |  |  |     # @api internal | 
					
						
							| 
									
										
										
										
											2021-09-29 15:12:53 -07:00
										 |  |  |     sig { params(cc: String).returns(Version) } | 
					
						
							| 
									
										
										
										
											2022-08-23 12:42:02 +01:00
										 |  |  |     def gcc_version(cc) | 
					
						
							| 
									
										
										
										
											2024-07-05 16:37:34 +01:00
										 |  |  |       (@gcc_version ||= T.let({}, T.nilable(T::Hash[String, Version]))).fetch(cc) do | 
					
						
							| 
									
										
										
										
											2021-02-10 09:12:11 -08:00
										 |  |  |         path = HOMEBREW_PREFIX/"opt/#{CompilerSelector.preferred_gcc}/bin"/cc | 
					
						
							| 
									
										
										
										
											2016-05-10 08:19:48 +01:00
										 |  |  |         path = locate(cc) unless path.exist? | 
					
						
							| 
									
										
										
										
											2024-07-05 21:14:03 +01:00
										 |  |  |         version = if path && | 
					
						
							|  |  |  |                      (build_version = `#{path} --version`[/gcc(?:(?:-\d+(?:\.\d)?)? \(.+\))? (\d+\.\d\.\d)/, 1]) | 
					
						
							|  |  |  |           Version.new(build_version) | 
					
						
							| 
									
										
										
										
											2016-11-03 16:48:51 -07:00
										 |  |  |         else | 
					
						
							|  |  |  |           Version::NULL | 
					
						
							|  |  |  |         end | 
					
						
							| 
									
										
										
										
											2022-08-23 12:42:02 +01:00
										 |  |  |         @gcc_version[cc] = version | 
					
						
							| 
									
										
										
										
											2016-05-10 08:19:48 +01:00
										 |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-29 15:12:53 -07:00
										 |  |  |     sig { void } | 
					
						
							| 
									
										
										
										
											2016-05-10 08:19:48 +01:00
										 |  |  |     def clear_version_cache | 
					
						
							| 
									
										
										
										
											2024-07-05 16:37:34 +01:00
										 |  |  |       @clang_version = @clang_build_version = T.let(nil, T.nilable(Version)) | 
					
						
							|  |  |  |       @gcc_version = T.let({}, T.nilable(T::Hash[String, Version])) | 
					
						
							| 
									
										
										
										
											2016-05-10 08:19:48 +01:00
										 |  |  |     end | 
					
						
							| 
									
										
										
										
											2016-12-30 20:17:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-25 11:04:37 +01:00
										 |  |  |     sig { returns(T::Boolean) } | 
					
						
							| 
									
										
										
										
											2022-11-09 14:45:43 +00:00
										 |  |  |     def needs_build_formulae? | 
					
						
							|  |  |  |       needs_libc_formula? || needs_compiler_formula? | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     sig { returns(T::Boolean) } | 
					
						
							|  |  |  |     def needs_libc_formula? | 
					
						
							| 
									
										
										
										
											2022-08-25 11:04:37 +01:00
										 |  |  |       false | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     sig { returns(T::Boolean) } | 
					
						
							| 
									
										
										
										
											2022-11-09 14:45:43 +00:00
										 |  |  |     def needs_compiler_formula? | 
					
						
							| 
									
										
										
										
											2022-08-25 11:04:37 +01:00
										 |  |  |       false | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-01 15:06:04 +01:00
										 |  |  |     sig { returns(T::Boolean) } | 
					
						
							|  |  |  |     def ca_file_handles_most_https_certificates? | 
					
						
							| 
									
										
										
										
											2022-02-21 22:49:55 +01:00
										 |  |  |       # The system CA file is too old for some modern HTTPS certificates on | 
					
						
							|  |  |  |       # older OS versions. | 
					
						
							|  |  |  |       ENV["HOMEBREW_SYSTEM_CA_CERTIFICATES_TOO_OLD"].nil? | 
					
						
							| 
									
										
										
										
											2021-10-01 15:06:04 +01:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-29 15:12:53 -07:00
										 |  |  |     sig { returns(T::Boolean) } | 
					
						
							| 
									
										
										
										
											2017-09-16 12:41:08 +01:00
										 |  |  |     def curl_handles_most_https_certificates? | 
					
						
							| 
									
										
										
										
											2016-12-30 20:17:34 +00:00
										 |  |  |       true | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2017-03-05 11:42:59 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-04 22:24:57 -04:00
										 |  |  |     sig { returns(T::Boolean) } | 
					
						
							|  |  |  |     def ca_file_substitution_required? | 
					
						
							|  |  |  |       (!ca_file_handles_most_https_certificates? || ENV["HOMEBREW_FORCE_BREWED_CA_CERTIFICATES"].present?) && | 
					
						
							|  |  |  |         !(HOMEBREW_PREFIX/"etc/ca-certificates/cert.pem").exist? | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     sig { returns(T::Boolean) } | 
					
						
							|  |  |  |     def curl_substitution_required? | 
					
						
							|  |  |  |       !curl_handles_most_https_certificates? && !HOMEBREW_BREWED_CURL_PATH.exist? | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-29 15:12:53 -07:00
										 |  |  |     sig { returns(T::Boolean) } | 
					
						
							| 
									
										
										
										
											2017-03-05 11:42:59 +01:00
										 |  |  |     def subversion_handles_most_https_certificates? | 
					
						
							|  |  |  |       true | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2020-04-06 13:04:48 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-29 18:16:34 -07:00
										 |  |  |     sig { returns(T::Hash[String, T.nilable(String)]) } | 
					
						
							| 
									
										
										
										
											2020-04-06 13:04:48 +01:00
										 |  |  |     def build_system_info | 
					
						
							|  |  |  |       { | 
					
						
							| 
									
										
										
										
											2022-05-30 04:25:24 +01:00
										 |  |  |         "os"         => HOMEBREW_SYSTEM, | 
					
						
							| 
									
										
										
										
											2020-04-06 13:04:48 +01:00
										 |  |  |         "os_version" => OS_VERSION, | 
					
						
							| 
									
										
										
										
											2021-09-29 17:43:47 -07:00
										 |  |  |         "cpu_family" => Hardware::CPU.family.to_s, | 
					
						
							| 
									
										
										
										
											2020-04-06 13:04:48 +01:00
										 |  |  |       } | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |     alias generic_build_system_info build_system_info | 
					
						
							| 
									
										
										
										
											2016-04-25 18:01:03 +01:00
										 |  |  |   end | 
					
						
							|  |  |  | end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | require "extend/os/development_tools" |