compilers: support more fails_with uses on GCC.
This commit is contained in:
parent
c65a392d47
commit
3cebcd43b7
@ -19,7 +19,7 @@ end
|
|||||||
#
|
#
|
||||||
# @api private
|
# @api private
|
||||||
class CompilerFailure
|
class CompilerFailure
|
||||||
attr_reader :name
|
attr_reader :type
|
||||||
|
|
||||||
def version(val = nil)
|
def version(val = nil)
|
||||||
@version = Version.parse(val.to_s) if val
|
@version = Version.parse(val.to_s) if val
|
||||||
@ -42,29 +42,51 @@ class CompilerFailure
|
|||||||
def self.create(spec, &block)
|
def self.create(spec, &block)
|
||||||
# Non-Apple compilers are in the format fails_with compiler => version
|
# Non-Apple compilers are in the format fails_with compiler => version
|
||||||
if spec.is_a?(Hash)
|
if spec.is_a?(Hash)
|
||||||
_, major_version = spec.first
|
compiler, major_version = spec.first
|
||||||
name = "gcc-#{major_version}"
|
raise ArgumentError, "The hash `fails_with` syntax only supports GCC" if compiler != :gcc
|
||||||
|
|
||||||
|
type = compiler
|
||||||
# so fails_with :gcc => '7' simply marks all 7 releases incompatible
|
# so fails_with :gcc => '7' simply marks all 7 releases incompatible
|
||||||
version = "#{major_version}.999"
|
version = "#{major_version}.999"
|
||||||
|
exact_major_match = true
|
||||||
else
|
else
|
||||||
name = spec
|
type = spec
|
||||||
version = 9999
|
version = 9999
|
||||||
|
exact_major_match = false
|
||||||
end
|
end
|
||||||
new(name, version, &block)
|
new(type, version, exact_major_match: exact_major_match, &block)
|
||||||
end
|
|
||||||
|
|
||||||
def initialize(name, version, &block)
|
|
||||||
@name = name
|
|
||||||
@version = Version.parse(version.to_s)
|
|
||||||
instance_eval(&block) if block
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def fails_with?(compiler)
|
def fails_with?(compiler)
|
||||||
name == compiler.name && version >= compiler.version
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
def inspect
|
def inspect
|
||||||
"#<#{self.class.name}: #{name} #{version}>"
|
"#<#{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
|
||||||
end
|
end
|
||||||
|
|
||||||
COLLECTIONS = {
|
COLLECTIONS = {
|
||||||
@ -81,7 +103,7 @@ class CompilerSelector
|
|||||||
extend T::Sig
|
extend T::Sig
|
||||||
include CompilerConstants
|
include CompilerConstants
|
||||||
|
|
||||||
Compiler = Struct.new(:name, :version)
|
Compiler = Struct.new(:type, :name, :version)
|
||||||
|
|
||||||
COMPILER_PRIORITY = {
|
COMPILER_PRIORITY = {
|
||||||
clang: [:clang, :gnu, :llvm_clang],
|
clang: [:clang, :gnu, :llvm_clang],
|
||||||
@ -130,15 +152,15 @@ class CompilerSelector
|
|||||||
case compiler
|
case compiler
|
||||||
when :gnu
|
when :gnu
|
||||||
gnu_gcc_versions.reverse_each do |v|
|
gnu_gcc_versions.reverse_each do |v|
|
||||||
name = "gcc-#{v}"
|
executable = "gcc-#{v}"
|
||||||
version = compiler_version(name)
|
version = compiler_version(executable)
|
||||||
yield Compiler.new(name, version) unless version.null?
|
yield Compiler.new(:gcc, executable, version) unless version.null?
|
||||||
end
|
end
|
||||||
when :llvm
|
when :llvm
|
||||||
next # no-op. DSL supported, compiler is not.
|
next # no-op. DSL supported, compiler is not.
|
||||||
else
|
else
|
||||||
version = compiler_version(compiler)
|
version = compiler_version(compiler)
|
||||||
yield Compiler.new(compiler, version) unless version.null?
|
yield Compiler.new(compiler, compiler, version) unless version.null?
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -9,31 +9,31 @@ describe CompilerFailure do
|
|||||||
describe "::create" do
|
describe "::create" do
|
||||||
it "creates a failure when given a symbol" do
|
it "creates a failure when given a symbol" do
|
||||||
failure = described_class.create(:clang)
|
failure = described_class.create(:clang)
|
||||||
expect(failure).to fail_with(double("Compiler", name: :clang, version: 600))
|
expect(failure).to fail_with(double("Compiler", type: :clang, name: :clang, version: 600))
|
||||||
end
|
end
|
||||||
|
|
||||||
it "can be given a build number in a block" do
|
it "can be given a build number in a block" do
|
||||||
failure = described_class.create(:clang) { build 700 }
|
failure = described_class.create(:clang) { build 700 }
|
||||||
expect(failure).to fail_with(double("Compiler", name: :clang, version: 700))
|
expect(failure).to fail_with(double("Compiler", type: :clang, name: :clang, version: 700))
|
||||||
end
|
end
|
||||||
|
|
||||||
it "can be given an empty block" do
|
it "can be given an empty block" do
|
||||||
failure = described_class.create(:clang) {}
|
failure = described_class.create(:clang) {}
|
||||||
expect(failure).to fail_with(double("Compiler", name: :clang, version: 600))
|
expect(failure).to fail_with(double("Compiler", type: :clang, name: :clang, version: 600))
|
||||||
end
|
end
|
||||||
|
|
||||||
it "creates a failure when given a hash" do
|
it "creates a failure when given a hash" do
|
||||||
failure = described_class.create(gcc: "7")
|
failure = described_class.create(gcc: "7")
|
||||||
expect(failure).to fail_with(double("Compiler", name: "gcc-7", version: "7"))
|
expect(failure).to fail_with(double("Compiler", type: :gcc, name: "gcc-7", version: Version.new("7")))
|
||||||
expect(failure).to fail_with(double("Compiler", name: "gcc-7", version: "7.1"))
|
expect(failure).to fail_with(double("Compiler", type: :gcc, name: "gcc-7", version: Version.new("7.1")))
|
||||||
expect(failure).not_to fail_with(double("Compiler", name: "gcc-6", version: "6.0"))
|
expect(failure).not_to fail_with(double("Compiler", type: :gcc, name: "gcc-6", version: Version.new("6.0")))
|
||||||
end
|
end
|
||||||
|
|
||||||
it "creates a failure when given a hash and a block with aversion" do
|
it "creates a failure when given a hash and a block with aversion" do
|
||||||
failure = described_class.create(gcc: "7") { version "7.1" }
|
failure = described_class.create(gcc: "7") { version "7.1" }
|
||||||
expect(failure).to fail_with(double("Compiler", name: "gcc-7", version: "7"))
|
expect(failure).to fail_with(double("Compiler", type: :gcc, name: "gcc-7", version: Version.new("7")))
|
||||||
expect(failure).to fail_with(double("Compiler", name: "gcc-7", version: "7.1"))
|
expect(failure).to fail_with(double("Compiler", type: :gcc, name: "gcc-7", version: Version.new("7.1")))
|
||||||
expect(failure).not_to fail_with(double("Compiler", name: "gcc-7", version: "7.2"))
|
expect(failure).not_to fail_with(double("Compiler", type: :gcc, name: "gcc-7", version: Version.new("7.2")))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -23,6 +23,7 @@ describe CompilerSelector do
|
|||||||
when "gcc-7" then Version.create("7.1")
|
when "gcc-7" then Version.create("7.1")
|
||||||
when "gcc-6" then Version.create("6.1")
|
when "gcc-6" then Version.create("6.1")
|
||||||
when "gcc-5" then Version.create("5.1")
|
when "gcc-5" then Version.create("5.1")
|
||||||
|
when "gcc-4.9" then Version.create("4.9.1")
|
||||||
else Version::NULL
|
else Version::NULL
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -45,29 +46,56 @@ describe CompilerSelector do
|
|||||||
|
|
||||||
it "returns gcc-6 if gcc formula offers gcc-6 on mac", :needs_macos do
|
it "returns gcc-6 if gcc formula offers gcc-6 on mac", :needs_macos do
|
||||||
software_spec.fails_with(:clang)
|
software_spec.fails_with(:clang)
|
||||||
allow(Formulary).to receive(:factory).with("gcc").and_return(double(version: "6.0"))
|
allow(Formulary).to receive(:factory).with("gcc").and_return(double(version: Version.new("6.0")))
|
||||||
expect(selector.compiler).to eq("gcc-6")
|
expect(selector.compiler).to eq("gcc-6")
|
||||||
end
|
end
|
||||||
|
|
||||||
it "returns gcc-5 if gcc formula offers gcc-5 on linux", :needs_linux do
|
it "returns gcc-5 if gcc formula offers gcc-5 on linux", :needs_linux do
|
||||||
software_spec.fails_with(:clang)
|
software_spec.fails_with(:clang)
|
||||||
allow(Formulary).to receive(:factory).with("gcc@5").and_return(double(version: "5.0"))
|
allow(Formulary).to receive(:factory).with("gcc@5").and_return(double(version: Version.new("5.0")))
|
||||||
expect(selector.compiler).to eq("gcc-5")
|
expect(selector.compiler).to eq("gcc-5")
|
||||||
end
|
end
|
||||||
|
|
||||||
it "returns gcc-6 if gcc formula offers gcc-6 and fails with gcc-5 and gcc-7 on linux", :needs_linux do
|
it "returns gcc-6 if gcc formula offers gcc-5 and fails with gcc-5 and gcc-7 on linux", :needs_linux do
|
||||||
software_spec.fails_with(:clang)
|
software_spec.fails_with(:clang)
|
||||||
software_spec.fails_with(gcc: "5")
|
software_spec.fails_with(gcc: "5")
|
||||||
software_spec.fails_with(gcc: "7")
|
software_spec.fails_with(gcc: "7")
|
||||||
allow(Formulary).to receive(:factory).with("gcc@5").and_return(double(version: "5.0"))
|
allow(Formulary).to receive(:factory).with("gcc@5").and_return(double(version: Version.new("5.0")))
|
||||||
expect(selector.compiler).to eq("gcc-6")
|
expect(selector.compiler).to eq("gcc-6")
|
||||||
end
|
end
|
||||||
|
|
||||||
it "raises an error when gcc or llvm is missing" do
|
it "returns gcc-7 if gcc formula offers gcc-5 and fails with gcc <= 6 on linux", :needs_linux do
|
||||||
|
software_spec.fails_with(:clang)
|
||||||
|
software_spec.fails_with(:gcc) { version "6" }
|
||||||
|
allow(Formulary).to receive(:factory).with("gcc@5").and_return(double(version: Version.new("5.0")))
|
||||||
|
expect(selector.compiler).to eq("gcc-7")
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns gcc-7 if gcc-7 is version 7.1 but spec fails with gcc-7 <= 7.0" do
|
||||||
|
software_spec.fails_with(:clang)
|
||||||
|
software_spec.fails_with(gcc: "7") { version "7.0" }
|
||||||
|
expect(selector.compiler).to eq("gcc-7")
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns gcc-6 if gcc-7 is version 7.1 but spec fails with gcc-7 <= 7.1" do
|
||||||
|
software_spec.fails_with(:clang)
|
||||||
|
software_spec.fails_with(gcc: "7") { version "7.1" }
|
||||||
|
expect(selector.compiler).to eq("gcc-6")
|
||||||
|
end
|
||||||
|
|
||||||
|
it "raises an error when gcc or llvm is missing (hash syntax)" do
|
||||||
software_spec.fails_with(:clang)
|
software_spec.fails_with(:clang)
|
||||||
software_spec.fails_with(gcc: "7")
|
software_spec.fails_with(gcc: "7")
|
||||||
software_spec.fails_with(gcc: "6")
|
software_spec.fails_with(gcc: "6")
|
||||||
software_spec.fails_with(gcc: "5")
|
software_spec.fails_with(gcc: "5")
|
||||||
|
software_spec.fails_with(gcc: "4.9")
|
||||||
|
|
||||||
|
expect { selector.compiler }.to raise_error(CompilerSelectionError)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "raises an error when gcc or llvm is missing (symbol syntax)" do
|
||||||
|
software_spec.fails_with(:clang)
|
||||||
|
software_spec.fails_with(:gcc)
|
||||||
|
|
||||||
expect { selector.compiler }.to raise_error(CompilerSelectionError)
|
expect { selector.compiler }.to raise_error(CompilerSelectionError)
|
||||||
end
|
end
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user