| 
									
										
										
										
											2020-10-10 14:16:11 +02:00
										 |  |  | # typed: true | 
					
						
							| 
									
										
										
										
											2019-04-19 15:38:03 +09:00
										 |  |  | # frozen_string_literal: true | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-29 10:56:24 +01:00
										 |  |  | # @private | 
					
						
							| 
									
										
										
										
											2014-07-02 21:57:52 -05:00
										 |  |  | module CompilerConstants | 
					
						
							| 
									
										
										
										
											2023-04-19 11:18:18 +02:00
										 |  |  |   GNU_GCC_VERSIONS = %w[4.9 5 6 7 8 9 10 11 12 13].freeze | 
					
						
							| 
									
										
										
										
											2024-01-18 22:18:42 +00:00
										 |  |  |   GNU_GCC_REGEXP = /^gcc-(4\.9|[5-9]|10|11|12|13)$/ | 
					
						
							| 
									
										
										
										
											2015-06-19 21:38:39 -04:00
										 |  |  |   COMPILER_SYMBOL_MAP = { | 
					
						
							| 
									
										
										
										
											2018-09-27 18:26:03 -07:00
										 |  |  |     "gcc"        => :gcc, | 
					
						
							| 
									
										
										
										
											2016-09-24 23:56:54 -04:00
										 |  |  |     "clang"      => :clang, | 
					
						
							|  |  |  |     "llvm_clang" => :llvm_clang, | 
					
						
							| 
									
										
										
										
											2016-09-17 15:17:27 +01:00
										 |  |  |   }.freeze | 
					
						
							| 
									
										
										
										
											2015-06-19 21:38:39 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-19 21:46:20 +09:00
										 |  |  |   COMPILERS = (COMPILER_SYMBOL_MAP.values + | 
					
						
							|  |  |  |                GNU_GCC_VERSIONS.map { |n| "gcc-#{n}" }).freeze | 
					
						
							| 
									
										
										
										
											2014-07-02 21:57:52 -05:00
										 |  |  | end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-14 03:21:41 +02:00
										 |  |  | # Class for checking compiler compatibility for a formula. | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | # @api private | 
					
						
							| 
									
										
										
										
											2012-03-18 13:58:13 -05:00
										 |  |  | class CompilerFailure | 
					
						
							| 
									
										
										
										
											2021-03-30 03:00:35 +01:00
										 |  |  |   attr_reader :type | 
					
						
							| 
									
										
										
										
											2016-11-03 16:48:51 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   def version(val = nil) | 
					
						
							| 
									
										
										
										
											2019-03-25 15:10:35 +00:00
										 |  |  |     @version = Version.parse(val.to_s) if val | 
					
						
							| 
									
										
										
										
											2019-01-26 17:13:14 +00:00
										 |  |  |     @version | 
					
						
							| 
									
										
										
										
											2016-11-03 16:48:51 -07:00
										 |  |  |   end | 
					
						
							| 
									
										
										
										
											2012-03-18 13:58:13 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-16 16:08:41 -05:00
										 |  |  |   # Allows Apple compiler `fails_with` statements to keep using `build` | 
					
						
							| 
									
										
										
										
											2020-11-05 17:17:03 -05:00
										 |  |  |   # even though `build` and `version` are the same internally. | 
					
						
							| 
									
										
										
										
											2016-09-23 18:13:48 +02:00
										 |  |  |   alias build version | 
					
						
							| 
									
										
										
										
											2014-06-16 16:08:41 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-05 17:17:03 -05:00
										 |  |  |   # The cause is no longer used so we need not hold a reference to the string. | 
					
						
							| 
									
										
										
										
											2014-09-21 00:53:15 -05:00
										 |  |  |   def cause(_); end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  |   def self.for_standard(standard) | 
					
						
							| 
									
										
										
										
											2014-08-01 20:15:58 -05:00
										 |  |  |     COLLECTIONS.fetch(standard) do | 
					
						
							| 
									
										
										
										
											2014-04-04 21:16:09 -07:00
										 |  |  |       raise ArgumentError, "\"#{standard}\" is not a recognized standard" | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-08-01 20:15:57 -05:00
										 |  |  |   def self.create(spec, &block) | 
					
						
							| 
									
										
										
										
											2013-06-28 01:38:09 -05:00
										 |  |  |     # Non-Apple compilers are in the format fails_with compiler => version | 
					
						
							| 
									
										
										
										
											2014-08-01 20:15:57 -05:00
										 |  |  |     if spec.is_a?(Hash) | 
					
						
							| 
									
										
										
										
											2021-03-30 03:00:35 +01:00
										 |  |  |       compiler, major_version = spec.first | 
					
						
							|  |  |  |       raise ArgumentError, "The hash `fails_with` syntax only supports GCC" if compiler != :gcc | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       type = compiler | 
					
						
							| 
									
										
										
										
											2019-01-08 19:13:46 +00:00
										 |  |  |       # so fails_with :gcc => '7' simply marks all 7 releases incompatible | 
					
						
							| 
									
										
										
										
											2014-08-01 20:15:57 -05:00
										 |  |  |       version = "#{major_version}.999" | 
					
						
							| 
									
										
										
										
											2021-03-30 03:00:35 +01:00
										 |  |  |       exact_major_match = true | 
					
						
							| 
									
										
										
										
											2013-12-12 14:53:53 -06:00
										 |  |  |     else | 
					
						
							| 
									
										
										
										
											2021-03-30 03:00:35 +01:00
										 |  |  |       type = spec | 
					
						
							| 
									
										
										
										
											2014-08-01 20:15:57 -05:00
										 |  |  |       version = 9999
 | 
					
						
							| 
									
										
										
										
											2021-03-30 03:00:35 +01:00
										 |  |  |       exact_major_match = false | 
					
						
							| 
									
										
										
										
											2013-09-28 12:21:16 -07:00
										 |  |  |     end | 
					
						
							| 
									
										
										
										
											2021-03-30 03:00:35 +01:00
										 |  |  |     new(type, version, exact_major_match: exact_major_match, &block) | 
					
						
							| 
									
										
										
										
											2012-03-18 13:58:13 -05:00
										 |  |  |   end | 
					
						
							| 
									
										
										
										
											2014-08-01 20:15:58 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-24 18:59:44 +02:00
										 |  |  |   def fails_with?(compiler) | 
					
						
							| 
									
										
										
										
											2021-03-30 03:00:35 +01:00
										 |  |  |     version_matched = if type != :gcc | 
					
						
							|  |  |  |       version >= compiler.version | 
					
						
							|  |  |  |     elsif @exact_major_match | 
					
						
							|  |  |  |       gcc_major(version) == gcc_major(compiler.version) && version >= compiler.version | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |       gcc_major(version) >= gcc_major(compiler.version) | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |     type == compiler.type && version_matched | 
					
						
							| 
									
										
										
										
											2014-08-03 10:47:47 -05:00
										 |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-08-03 15:28:26 -05:00
										 |  |  |   def inspect | 
					
						
							| 
									
										
										
										
											2021-03-30 03:00:35 +01:00
										 |  |  |     "#<#{self.class.name}: #{type} #{version}>" | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   private | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   def initialize(type, version, exact_major_match:, &block) | 
					
						
							|  |  |  |     @type = type | 
					
						
							|  |  |  |     @version = Version.parse(version.to_s) | 
					
						
							|  |  |  |     @exact_major_match = exact_major_match | 
					
						
							|  |  |  |     instance_eval(&block) if block | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   def gcc_major(version) | 
					
						
							|  |  |  |     if version.major >= 5
 | 
					
						
							|  |  |  |       Version.new(version.major.to_s) | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |       version.major_minor | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2014-08-03 15:28:26 -05:00
										 |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-08-01 20:15:58 -05:00
										 |  |  |   COLLECTIONS = { | 
					
						
							| 
									
										
										
										
											2016-09-17 15:32:44 +01:00
										 |  |  |     openmp: [ | 
					
						
							| 
									
										
										
										
											2015-04-21 17:51:55 -04:00
										 |  |  |       create(:clang), | 
					
						
							| 
									
										
										
										
											2015-12-30 21:14:01 +00:00
										 |  |  |     ], | 
					
						
							| 
									
										
										
										
											2016-09-17 15:17:27 +01:00
										 |  |  |   }.freeze | 
					
						
							| 
									
										
										
										
											2012-03-18 13:58:13 -05:00
										 |  |  | end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-14 03:21:41 +02:00
										 |  |  | # Class for selecting a compiler for a formula. | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | # @api private | 
					
						
							| 
									
										
										
										
											2014-09-18 15:50:54 -05:00
										 |  |  | class CompilerSelector | 
					
						
							|  |  |  |   include CompilerConstants | 
					
						
							| 
									
										
										
										
											2012-03-18 13:58:13 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-30 03:00:35 +01:00
										 |  |  |   Compiler = Struct.new(:type, :name, :version) | 
					
						
							| 
									
										
										
										
											2013-03-13 02:07:01 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-18 15:50:54 -05:00
										 |  |  |   COMPILER_PRIORITY = { | 
					
						
							| 
									
										
										
										
											2019-01-26 17:13:14 +00:00
										 |  |  |     clang: [:clang, :gnu, :llvm_clang], | 
					
						
							|  |  |  |     gcc:   [:gnu, :gcc, :llvm_clang, :clang], | 
					
						
							| 
									
										
										
										
											2016-09-17 15:17:27 +01:00
										 |  |  |   }.freeze | 
					
						
							| 
									
										
										
										
											2012-03-18 13:58:13 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  |   def self.select_for(formula, compilers = self.compilers) | 
					
						
							| 
									
										
										
										
											2016-04-25 18:01:03 +01:00
										 |  |  |     new(formula, DevelopmentTools, compilers).compiler | 
					
						
							| 
									
										
										
										
											2013-03-13 02:07:01 -05:00
										 |  |  |   end | 
					
						
							| 
									
										
										
										
											2014-09-18 15:50:54 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-18 15:50:54 -05:00
										 |  |  |   def self.compilers | 
					
						
							| 
									
										
										
										
											2016-04-25 18:01:03 +01:00
										 |  |  |     COMPILER_PRIORITY.fetch(DevelopmentTools.default_compiler) | 
					
						
							| 
									
										
										
										
											2014-09-18 15:50:54 -05:00
										 |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-18 15:50:54 -05:00
										 |  |  |   attr_reader :formula, :failures, :versions, :compilers | 
					
						
							| 
									
										
										
										
											2014-09-18 15:50:54 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-18 15:50:54 -05:00
										 |  |  |   def initialize(formula, versions, compilers) | 
					
						
							| 
									
										
										
										
											2014-09-18 15:50:54 -05:00
										 |  |  |     @formula = formula | 
					
						
							|  |  |  |     @failures = formula.compiler_failures | 
					
						
							| 
									
										
										
										
											2014-06-11 21:05:31 -05:00
										 |  |  |     @versions = versions | 
					
						
							| 
									
										
										
										
											2014-09-18 15:50:54 -05:00
										 |  |  |     @compilers = compilers | 
					
						
							| 
									
										
										
										
											2012-03-18 13:58:13 -05:00
										 |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-13 02:07:01 -05:00
										 |  |  |   def compiler | 
					
						
							| 
									
										
										
										
											2014-09-18 15:50:54 -05:00
										 |  |  |     find_compiler { |c| return c.name unless fails_with?(c) } | 
					
						
							| 
									
										
										
										
											2016-09-17 15:17:27 +01:00
										 |  |  |     raise CompilerSelectionError, formula | 
					
						
							| 
									
										
										
										
											2013-03-13 02:07:01 -05:00
										 |  |  |   end | 
					
						
							| 
									
										
										
										
											2012-03-18 13:58:13 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-03 21:28:11 +01:00
										 |  |  |   sig { returns(String) } | 
					
						
							| 
									
										
										
										
											2021-02-08 20:06:09 +01:00
										 |  |  |   def self.preferred_gcc | 
					
						
							| 
									
										
										
										
											2021-02-03 21:28:11 +01:00
										 |  |  |     "gcc" | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-08 20:06:09 +01:00
										 |  |  |   private | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-31 21:42:05 +08:00
										 |  |  |   def gnu_gcc_versions | 
					
						
							|  |  |  |     # prioritize gcc version provided by gcc formula. | 
					
						
							| 
									
										
										
										
											2021-02-08 20:06:09 +01:00
										 |  |  |     v = Formulary.factory(CompilerSelector.preferred_gcc).version.to_s.slice(/\d+/) | 
					
						
							| 
									
										
										
										
											2019-03-31 21:42:05 +08:00
										 |  |  |     GNU_GCC_VERSIONS - [v] + [v] # move the version to the end of the list | 
					
						
							|  |  |  |   rescue FormulaUnavailableError | 
					
						
							|  |  |  |     GNU_GCC_VERSIONS | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-18 15:50:54 -05:00
										 |  |  |   def find_compiler | 
					
						
							|  |  |  |     compilers.each do |compiler| | 
					
						
							|  |  |  |       case compiler | 
					
						
							|  |  |  |       when :gnu | 
					
						
							| 
									
										
										
										
											2019-03-31 21:42:05 +08:00
										 |  |  |         gnu_gcc_versions.reverse_each do |v| | 
					
						
							| 
									
										
										
										
											2021-03-30 03:00:35 +01:00
										 |  |  |           executable = "gcc-#{v}" | 
					
						
							|  |  |  |           version = compiler_version(executable) | 
					
						
							|  |  |  |           yield Compiler.new(:gcc, executable, version) unless version.null? | 
					
						
							| 
									
										
										
										
											2014-09-18 15:50:54 -05:00
										 |  |  |         end | 
					
						
							| 
									
										
										
										
											2016-05-22 09:40:08 +01:00
										 |  |  |       when :llvm | 
					
						
							| 
									
										
										
										
											2016-11-13 23:37:51 +01:00
										 |  |  |         next # no-op. DSL supported, compiler is not. | 
					
						
							| 
									
										
										
										
											2014-09-18 15:50:54 -05:00
										 |  |  |       else | 
					
						
							| 
									
										
										
										
											2015-05-17 19:18:32 -04:00
										 |  |  |         version = compiler_version(compiler) | 
					
						
							| 
									
										
										
										
											2021-03-30 03:00:35 +01:00
										 |  |  |         yield Compiler.new(compiler, compiler, version) unless version.null? | 
					
						
							| 
									
										
										
										
											2014-09-18 15:50:54 -05:00
										 |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-18 15:50:54 -05:00
										 |  |  |   def fails_with?(compiler) | 
					
						
							| 
									
										
										
										
											2016-09-24 18:59:44 +02:00
										 |  |  |     failures.any? { |failure| failure.fails_with?(compiler) } | 
					
						
							| 
									
										
										
										
											2014-09-18 15:50:54 -05:00
										 |  |  |   end | 
					
						
							| 
									
										
										
										
											2015-05-17 19:18:32 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |   def compiler_version(name) | 
					
						
							| 
									
										
										
										
											2018-09-27 18:26:03 -07:00
										 |  |  |     case name.to_s | 
					
						
							|  |  |  |     when "gcc", GNU_GCC_REGEXP | 
					
						
							| 
									
										
										
										
											2022-08-23 12:42:02 +01:00
										 |  |  |       versions.gcc_version(name.to_s) | 
					
						
							| 
									
										
										
										
											2015-05-17 19:18:32 -04:00
										 |  |  |     else | 
					
						
							| 
									
										
										
										
											2023-12-18 09:34:01 -08:00
										 |  |  |       versions.send(:"#{name}_build_version") | 
					
						
							| 
									
										
										
										
											2015-05-17 19:18:32 -04:00
										 |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							| 
									
										
										
										
											2012-03-18 13:58:13 -05:00
										 |  |  | end | 
					
						
							| 
									
										
										
										
											2021-02-03 21:28:11 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | require "extend/os/compilers" |