| 
									
										
										
										
											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 | 
					
						
							| 
									
										
										
										
											2020-05-01 00:59:08 +10:00
										 |  |  |   GNU_GCC_VERSIONS = %w[4.9 5 6 7 8 9 10].freeze | 
					
						
							|  |  |  |   GNU_GCC_REGEXP = /^gcc-(4\.9|[5-9]|10)$/.freeze | 
					
						
							| 
									
										
										
										
											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 | 
					
						
							| 
									
										
										
										
											2014-08-03 10:47:47 -05:00
										 |  |  |   attr_reader :name | 
					
						
							| 
									
										
										
										
											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` | 
					
						
							|  |  |  |   # 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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-21 00:53:15 -05:00
										 |  |  |   # The cause is no longer used so we need not hold a reference to the string | 
					
						
							|  |  |  |   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) | 
					
						
							| 
									
										
										
										
											2015-12-26 23:00:38 +01:00
										 |  |  |       _, major_version = spec.first | 
					
						
							| 
									
										
										
										
											2014-08-03 10:47:47 -05:00
										 |  |  |       name = "gcc-#{major_version}" | 
					
						
							| 
									
										
										
										
											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" | 
					
						
							| 
									
										
										
										
											2013-12-12 14:53:53 -06:00
										 |  |  |     else | 
					
						
							| 
									
										
										
										
											2014-08-03 10:47:47 -05:00
										 |  |  |       name = spec | 
					
						
							| 
									
										
										
										
											2014-08-01 20:15:57 -05:00
										 |  |  |       version = 9999
 | 
					
						
							| 
									
										
										
										
											2013-09-28 12:21:16 -07:00
										 |  |  |     end | 
					
						
							| 
									
										
										
										
											2014-08-03 11:15:39 -05:00
										 |  |  |     new(name, version, &block) | 
					
						
							| 
									
										
										
										
											2014-08-01 20:15:57 -05:00
										 |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-08-03 10:47:47 -05:00
										 |  |  |   def initialize(name, version, &block) | 
					
						
							| 
									
										
										
										
											2014-08-03 10:47:47 -05:00
										 |  |  |     @name = name | 
					
						
							| 
									
										
										
										
											2016-11-03 16:48:51 -07:00
										 |  |  |     @version = Version.parse(version.to_s) | 
					
						
							| 
									
										
										
										
											2014-08-01 20:15:57 -05:00
										 |  |  |     instance_eval(&block) if block_given? | 
					
						
							| 
									
										
										
										
											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) | 
					
						
							| 
									
										
										
										
											2014-08-03 13:12:59 -05:00
										 |  |  |     name == compiler.name && version >= compiler.version | 
					
						
							| 
									
										
										
										
											2014-08-03 10:47:47 -05:00
										 |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-08-03 15:28:26 -05:00
										 |  |  |   def inspect | 
					
						
							|  |  |  |     "#<#{self.class.name}: #{name} #{version}>" | 
					
						
							|  |  |  |   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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-18 15:50:54 -05:00
										 |  |  |   Compiler = Struct.new(: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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-13 02:07:01 -05:00
										 |  |  |   private | 
					
						
							| 
									
										
										
										
											2012-03-18 13:58:13 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-31 21:42:05 +08:00
										 |  |  |   def gnu_gcc_versions | 
					
						
							|  |  |  |     # prioritize gcc version provided by gcc formula. | 
					
						
							| 
									
										
										
										
											2020-05-09 11:06:02 +01:00
										 |  |  |     v = Formulary.factory("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| | 
					
						
							| 
									
										
										
										
											2015-05-07 01:12:24 -07:00
										 |  |  |           name = "gcc-#{v}" | 
					
						
							| 
									
										
										
										
											2015-05-17 19:18:32 -04:00
										 |  |  |           version = compiler_version(name) | 
					
						
							| 
									
										
										
										
											2016-11-08 13:25:44 -08:00
										 |  |  |           yield Compiler.new(name, 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) | 
					
						
							| 
									
										
										
										
											2016-11-08 13:25:44 -08:00
										 |  |  |         yield Compiler.new(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 | 
					
						
							|  |  |  |       versions.non_apple_gcc_version(name.to_s) | 
					
						
							| 
									
										
										
										
											2015-05-17 19:18:32 -04:00
										 |  |  |     else | 
					
						
							|  |  |  |       versions.send("#{name}_build_version") | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							| 
									
										
										
										
											2012-03-18 13:58:13 -05:00
										 |  |  | end |