Replace CompilerQueue with predetermined priority lists
This commit is contained in:
parent
288c7974dc
commit
04dae13ae7
@ -68,74 +68,65 @@ class CompilerFailure
|
|||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
class CompilerQueue
|
|
||||||
def initialize
|
|
||||||
@array = []
|
|
||||||
end
|
|
||||||
|
|
||||||
def <<(o)
|
|
||||||
@array << o
|
|
||||||
self
|
|
||||||
end
|
|
||||||
|
|
||||||
def pop
|
|
||||||
@array.delete(@array.max { |a, b| a.priority <=> b.priority })
|
|
||||||
end
|
|
||||||
|
|
||||||
def empty?
|
|
||||||
@array.empty?
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
class CompilerSelector
|
class CompilerSelector
|
||||||
Compiler = Struct.new(:name, :version, :priority)
|
include CompilerConstants
|
||||||
|
|
||||||
attr_reader :formula
|
Compiler = Struct.new(:name, :version)
|
||||||
|
|
||||||
def initialize(formula, versions=MacOS)
|
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 self.select_for(formula)
|
||||||
|
compilers = COMPILER_PRIORITY.fetch(MacOS.default_compiler)
|
||||||
|
new(formula, MacOS, compilers).compiler
|
||||||
|
end
|
||||||
|
|
||||||
|
attr_reader :formula, :failures, :versions, :compilers
|
||||||
|
|
||||||
|
def initialize(formula, versions, compilers)
|
||||||
@formula = formula
|
@formula = formula
|
||||||
@failures = formula.compiler_failures
|
@failures = formula.compiler_failures
|
||||||
@versions = versions
|
@versions = versions
|
||||||
@compilers = CompilerQueue.new
|
@compilers = compilers
|
||||||
%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
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Attempts to select an appropriate alternate compiler, but
|
|
||||||
# if none can be found raises CompilerError instead
|
|
||||||
def compiler
|
def compiler
|
||||||
while cc = @compilers.pop
|
find_compiler { |c| return c.name unless fails_with?(c) }
|
||||||
return cc.name unless fails_with?(cc)
|
|
||||||
end
|
|
||||||
raise CompilerSelectionError.new(formula)
|
raise CompilerSelectionError.new(formula)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def fails_with?(compiler)
|
def find_compiler
|
||||||
@failures.any? { |failure| failure === 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
|
end
|
||||||
|
|
||||||
def priority_for(cc)
|
def fails_with?(compiler)
|
||||||
case cc
|
failures.any? { |failure| failure === compiler }
|
||||||
when :clang then @versions.clang_build_version >= 318 ? 3 : 0.5
|
end
|
||||||
when :gcc then 2.5
|
|
||||||
when :llvm then 2
|
def compiler_version(name)
|
||||||
when :gcc_4_0 then 0.25
|
case name
|
||||||
|
when GNU_GCC_REGEXP
|
||||||
|
versions.non_apple_gcc_version(name)
|
||||||
|
else
|
||||||
|
versions.send("#{name}_build_version")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -131,7 +131,7 @@ module SharedEnvExtension
|
|||||||
# an alternate compiler, altering the value of environment variables.
|
# an alternate compiler, altering the value of environment variables.
|
||||||
# If no valid compiler is found, raises an exception.
|
# If no valid compiler is found, raises an exception.
|
||||||
def validate_cc!(formula)
|
def validate_cc!(formula)
|
||||||
send CompilerSelector.new(formula).compiler
|
send CompilerSelector.select_for(formula)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Snow Leopard defines an NCURSES value the opposite of most distros
|
# Snow Leopard defines an NCURSES value the opposite of most distros
|
||||||
|
|||||||
@ -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
|
|
||||||
@ -14,17 +14,18 @@ class CompilerSelectorTests < Homebrew::TestCase
|
|||||||
attr_accessor :gcc_4_0_build_version, :gcc_build_version,
|
attr_accessor :gcc_4_0_build_version, :gcc_build_version,
|
||||||
:llvm_build_version, :clang_build_version
|
:llvm_build_version, :clang_build_version
|
||||||
|
|
||||||
def initialize(versions={})
|
def initialize
|
||||||
{
|
@gcc_4_0_build_version = nil
|
||||||
:gcc_4_0_build_version => nil,
|
@gcc_build_version = 5666
|
||||||
:gcc_build_version => 5666,
|
@llvm_build_version = 2336
|
||||||
:llvm_build_version => 2336,
|
@clang_build_version = 425
|
||||||
:clang_build_version => 425,
|
|
||||||
}.merge(versions).each { |k, v| instance_variable_set("@#{k}", v) }
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def non_apple_gcc_version(name)
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -32,14 +33,17 @@ class CompilerSelectorTests < Homebrew::TestCase
|
|||||||
@f = Double.new
|
@f = Double.new
|
||||||
@cc = :clang
|
@cc = :clang
|
||||||
@versions = CompilerVersions.new
|
@versions = CompilerVersions.new
|
||||||
|
@selector = CompilerSelector.new(
|
||||||
|
@f, @versions, [:clang, :gcc, :llvm, :gnu]
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
def actual_cc
|
def actual_cc
|
||||||
CompilerSelector.new(@f, @versions).compiler
|
@selector.compiler
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_all_compiler_failures
|
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 }
|
assert_raises(CompilerSelectionError) { actual_cc }
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -68,17 +72,17 @@ class CompilerSelectorTests < Homebrew::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
def test_mixed_failures_1
|
def test_mixed_failures_1
|
||||||
|
@f << :clang << :gcc
|
||||||
|
assert_equal :llvm, actual_cc
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_mixed_failures_2
|
||||||
@f << :clang << :llvm
|
@f << :clang << :llvm
|
||||||
assert_equal :gcc, actual_cc
|
assert_equal :gcc, actual_cc
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_mixed_failures_2
|
|
||||||
@f << :gcc << :clang << { :gcc => "4.8" }
|
|
||||||
assert_equal :llvm, actual_cc
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_mixed_failures_3
|
def test_mixed_failures_3
|
||||||
@f << :llvm << :gcc
|
@f << :gcc << :llvm
|
||||||
assert_equal :clang, actual_cc
|
assert_equal :clang, actual_cc
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -87,10 +91,9 @@ class CompilerSelectorTests < Homebrew::TestCase
|
|||||||
assert_equal :gcc, actual_cc
|
assert_equal :gcc, actual_cc
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_older_clang_precedence
|
def test_mixed_failures_5
|
||||||
@versions.clang_build_version = 211
|
@f << :clang << :gcc << :llvm << { :gcc => "4.8" }
|
||||||
@f << :gcc << { :gcc => "4.8" }
|
assert_equal "gcc-4.7", actual_cc
|
||||||
assert_equal :llvm, actual_cc
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_llvm_precedence
|
def test_llvm_precedence
|
||||||
@ -100,13 +103,13 @@ class CompilerSelectorTests < Homebrew::TestCase
|
|||||||
|
|
||||||
def test_missing_gcc
|
def test_missing_gcc
|
||||||
@versions.gcc_build_version = nil
|
@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 }
|
assert_raises(CompilerSelectionError) { actual_cc }
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_missing_llvm_and_gcc
|
def test_missing_llvm_and_gcc
|
||||||
@versions.gcc_build_version = @versions.llvm_build_version = nil
|
@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 }
|
assert_raises(CompilerSelectionError) { actual_cc }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user