diff options
| -rw-r--r-- | Library/Homebrew/compilers.rb | 87 | ||||
| -rw-r--r-- | Library/Homebrew/extend/ENV/shared.rb | 2 | ||||
| -rw-r--r-- | Library/Homebrew/test/test_compiler_queue.rb | 38 | ||||
| -rw-r--r-- | Library/Homebrew/test/test_compiler_selector.rb | 45 |
4 files changed, 64 insertions, 108 deletions
diff --git a/Library/Homebrew/compilers.rb b/Library/Homebrew/compilers.rb index ba1300def..d841e18d0 100644 --- a/Library/Homebrew/compilers.rb +++ b/Library/Homebrew/compilers.rb @@ -68,74 +68,65 @@ class CompilerFailure } end -class CompilerQueue - def initialize - @array = [] - end +class CompilerSelector + include CompilerConstants - def <<(o) - @array << o - self - end + Compiler = Struct.new(:name, :version) - def pop - @array.delete(@array.max { |a, b| a.priority <=> b.priority }) - end + COMPILER_PRIORITY = { + :clang => [:clang, :gcc, :llvm, :gnu, :gcc_4_0], + :gcc => [:gcc, :llvm, :gnu, :clang, :gcc_4_0], + :llvm => [:llvm, :gcc, :gnu, :clang, :gcc_4_0], + :gcc_4_0 => [:gcc_4_0, :gcc, :llvm, :gnu, :clang], + } - def empty? - @array.empty? + def self.select_for(formula) + compilers = COMPILER_PRIORITY.fetch(MacOS.default_compiler) + new(formula, MacOS, compilers).compiler end -end - -class CompilerSelector - Compiler = Struct.new(:name, :version, :priority) - attr_reader :formula + attr_reader :formula, :failures, :versions, :compilers - def initialize(formula, versions=MacOS) + def initialize(formula, versions, compilers) @formula = formula @failures = formula.compiler_failures @versions = versions - @compilers = CompilerQueue.new - %w{clang llvm gcc gcc_4_0}.map(&:to_sym).each do |cc| - version = @versions.send("#{cc}_build_version") - unless version.nil? - @compilers << Compiler.new(cc, version, priority_for(cc)) - end - end - - # non-Apple GCC 4.x - CompilerConstants::GNU_GCC_VERSIONS.each do |v| - name = "gcc-4.#{v}" - version = @versions.non_apple_gcc_version(name) - unless version.nil? - # priority is based on version, with newest preferred first - @compilers << Compiler.new(name, version, 1.0 + v/10.0) - end - end + @compilers = compilers end - # Attempts to select an appropriate alternate compiler, but - # if none can be found raises CompilerError instead def compiler - while cc = @compilers.pop - return cc.name unless fails_with?(cc) - end + find_compiler { |c| return c.name unless fails_with?(c) } raise CompilerSelectionError.new(formula) end private + def find_compiler + compilers.each do |compiler| + case compiler + when :gnu + GNU_GCC_VERSIONS.reverse_each do |v| + name = "gcc-4.#{v}" + version = compiler_version(name) + yield Compiler.new(name, version) if version + end + else + version = compiler_version(compiler) + yield Compiler.new(compiler, version) if version + end + end + end + def fails_with?(compiler) - @failures.any? { |failure| failure === compiler } + failures.any? { |failure| failure === compiler } end - def priority_for(cc) - case cc - when :clang then @versions.clang_build_version >= 318 ? 3 : 0.5 - when :gcc then 2.5 - when :llvm then 2 - when :gcc_4_0 then 0.25 + def compiler_version(name) + case name + when GNU_GCC_REGEXP + versions.non_apple_gcc_version(name) + else + versions.send("#{name}_build_version") end end end diff --git a/Library/Homebrew/extend/ENV/shared.rb b/Library/Homebrew/extend/ENV/shared.rb index 066266434..9ef512b92 100644 --- a/Library/Homebrew/extend/ENV/shared.rb +++ b/Library/Homebrew/extend/ENV/shared.rb @@ -131,7 +131,7 @@ module SharedEnvExtension # an alternate compiler, altering the value of environment variables. # If no valid compiler is found, raises an exception. def validate_cc!(formula) - send CompilerSelector.new(formula).compiler + send CompilerSelector.select_for(formula) end # Snow Leopard defines an NCURSES value the opposite of most distros diff --git a/Library/Homebrew/test/test_compiler_queue.rb b/Library/Homebrew/test/test_compiler_queue.rb deleted file mode 100644 index 16d3d3479..000000000 --- a/Library/Homebrew/test/test_compiler_queue.rb +++ /dev/null @@ -1,38 +0,0 @@ -require 'testing_env' -require 'compilers' - -class CompilerQueueTests < Homebrew::TestCase - FakeCompiler = Struct.new(:name, :priority) - - def setup - @q = CompilerQueue.new - end - - def test_shovel_returns_self - assert_same @q, @q << Object.new - end - - def test_empty - assert_empty @q - end - - def test_queues_items - a = FakeCompiler.new(:foo, 0) - b = FakeCompiler.new(:bar, 0) - @q << a << b - assert_equal a, @q.pop - assert_equal b, @q.pop - assert_nil @q.pop - end - - def test_pops_items_by_priority - a = FakeCompiler.new(:foo, 0) - b = FakeCompiler.new(:bar, 0.5) - c = FakeCompiler.new(:baz, 1) - @q << a << b << c - assert_equal c, @q.pop - assert_equal b, @q.pop - assert_equal a, @q.pop - assert_nil @q.pop - end -end diff --git a/Library/Homebrew/test/test_compiler_selector.rb b/Library/Homebrew/test/test_compiler_selector.rb index 413e92657..a4a2986a0 100644 --- a/Library/Homebrew/test/test_compiler_selector.rb +++ b/Library/Homebrew/test/test_compiler_selector.rb @@ -14,17 +14,18 @@ class CompilerSelectorTests < Homebrew::TestCase attr_accessor :gcc_4_0_build_version, :gcc_build_version, :llvm_build_version, :clang_build_version - def initialize(versions={}) - { - :gcc_4_0_build_version => nil, - :gcc_build_version => 5666, - :llvm_build_version => 2336, - :clang_build_version => 425, - }.merge(versions).each { |k, v| instance_variable_set("@#{k}", v) } + def initialize + @gcc_4_0_build_version = nil + @gcc_build_version = 5666 + @llvm_build_version = 2336 + @clang_build_version = 425 end def non_apple_gcc_version(name) - name == "gcc-4.8" ? "4.8.1" : nil + case name + when "gcc-4.8" then "4.8.1" + when "gcc-4.7" then "4.7.1" + end end end @@ -32,14 +33,17 @@ class CompilerSelectorTests < Homebrew::TestCase @f = Double.new @cc = :clang @versions = CompilerVersions.new + @selector = CompilerSelector.new( + @f, @versions, [:clang, :gcc, :llvm, :gnu] + ) end def actual_cc - CompilerSelector.new(@f, @versions).compiler + @selector.compiler end def test_all_compiler_failures - @f << :clang << :llvm << :gcc << { :gcc => "4.8" } + @f << :clang << :llvm << :gcc << { :gcc => "4.8" } << { :gcc => "4.7" } assert_raises(CompilerSelectionError) { actual_cc } end @@ -68,17 +72,17 @@ class CompilerSelectorTests < Homebrew::TestCase end def test_mixed_failures_1 - @f << :clang << :llvm - assert_equal :gcc, actual_cc + @f << :clang << :gcc + assert_equal :llvm, actual_cc end def test_mixed_failures_2 - @f << :gcc << :clang << { :gcc => "4.8" } - assert_equal :llvm, actual_cc + @f << :clang << :llvm + assert_equal :gcc, actual_cc end def test_mixed_failures_3 - @f << :llvm << :gcc + @f << :gcc << :llvm assert_equal :clang, actual_cc end @@ -87,10 +91,9 @@ class CompilerSelectorTests < Homebrew::TestCase assert_equal :gcc, actual_cc end - def test_older_clang_precedence - @versions.clang_build_version = 211 - @f << :gcc << { :gcc => "4.8" } - assert_equal :llvm, actual_cc + def test_mixed_failures_5 + @f << :clang << :gcc << :llvm << { :gcc => "4.8" } + assert_equal "gcc-4.7", actual_cc end def test_llvm_precedence @@ -100,13 +103,13 @@ class CompilerSelectorTests < Homebrew::TestCase def test_missing_gcc @versions.gcc_build_version = nil - @f << :clang << :llvm << { :gcc => "4.8" } + @f << :clang << :llvm << { :gcc => "4.8" } << { :gcc => "4.7" } assert_raises(CompilerSelectionError) { actual_cc } end def test_missing_llvm_and_gcc @versions.gcc_build_version = @versions.llvm_build_version = nil - @f << :clang << { :gcc => "4.8" } + @f << :clang << { :gcc => "4.8" } << { :gcc => "4.7" } assert_raises(CompilerSelectionError) { actual_cc } end end |
