Use polymorphism to simplify stdlib compatibility check
This commit is contained in:
parent
90e370d2ef
commit
142beddd7a
@ -172,7 +172,7 @@ class Build
|
|||||||
# This currently only tracks a single C++ stdlib per dep,
|
# This currently only tracks a single C++ stdlib per dep,
|
||||||
# though it's possible for different libs/executables in
|
# though it's possible for different libs/executables in
|
||||||
# a given formula to link to different ones.
|
# a given formula to link to different ones.
|
||||||
stdlib_in_use = CxxStdlib.new(stdlibs.first, ENV.compiler)
|
stdlib_in_use = CxxStdlib.create(stdlibs.first, ENV.compiler)
|
||||||
begin
|
begin
|
||||||
stdlib_in_use.check_dependencies(f, deps)
|
stdlib_in_use.check_dependencies(f, deps)
|
||||||
rescue IncompatibleCxxStdlibs => e
|
rescue IncompatibleCxxStdlibs => e
|
||||||
|
|||||||
@ -1,37 +1,29 @@
|
|||||||
require "compilers"
|
require "compilers"
|
||||||
|
|
||||||
class CxxStdlib
|
class CxxStdlib
|
||||||
attr_reader :type, :compiler
|
include CompilerConstants
|
||||||
|
|
||||||
def initialize(type, compiler)
|
def self.create(type, compiler)
|
||||||
if type && ![:libstdcxx, :libcxx].include?(type)
|
if type && ![:libstdcxx, :libcxx].include?(type)
|
||||||
raise ArgumentError, "Invalid C++ stdlib type: #{type}"
|
raise ArgumentError, "Invalid C++ stdlib type: #{type}"
|
||||||
end
|
end
|
||||||
|
klass = GNU_GCC_REGEXP === compiler.to_s ? GnuStdlib : AppleStdlib
|
||||||
|
klass.new(type, compiler)
|
||||||
|
end
|
||||||
|
|
||||||
|
attr_reader :type, :compiler
|
||||||
|
|
||||||
|
def initialize(type, compiler)
|
||||||
@type = type
|
@type = type
|
||||||
@compiler = compiler.to_sym
|
@compiler = compiler.to_sym
|
||||||
end
|
end
|
||||||
|
|
||||||
def apple_compiler?
|
# If either package doesn't use C++, all is well
|
||||||
not compiler.to_s =~ CompilerConstants::GNU_GCC_REGEXP
|
# libstdc++ and libc++ aren't ever intercompatible
|
||||||
end
|
# libstdc++ is compatible across Apple compilers, but
|
||||||
|
# not between Apple and GNU compilers, or between GNU compiler versions
|
||||||
def compatible_with?(other)
|
def compatible_with?(other)
|
||||||
# If either package doesn't use C++, all is well
|
(type.nil? || other.type.nil?) || type == other.type
|
||||||
return true if type.nil? || other.type.nil?
|
|
||||||
|
|
||||||
# libstdc++ and libc++ aren't ever intercompatible
|
|
||||||
return false unless type == other.type
|
|
||||||
|
|
||||||
# libstdc++ is compatible across Apple compilers, but
|
|
||||||
# not between Apple and GNU compilers, or between GNU compiler versions
|
|
||||||
return false if apple_compiler? && !other.apple_compiler?
|
|
||||||
if compiler.to_s =~ CompilerConstants::GNU_GCC_REGEXP
|
|
||||||
return false unless other.compiler.to_s =~ CompilerConstants::GNU_GCC_REGEXP
|
|
||||||
return false unless compiler.to_s[4..6] == other.compiler.to_s[4..6]
|
|
||||||
end
|
|
||||||
|
|
||||||
true
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def check_dependencies(formula, deps)
|
def check_dependencies(formula, deps)
|
||||||
@ -53,4 +45,26 @@ class CxxStdlib
|
|||||||
def type_string
|
def type_string
|
||||||
type.to_s.gsub(/cxx$/, 'c++')
|
type.to_s.gsub(/cxx$/, 'c++')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
class AppleStdlib < CxxStdlib
|
||||||
|
def apple_compiler?
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
def compatible_with?(other)
|
||||||
|
super && other.apple_compiler?
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class GnuStdlib < CxxStdlib
|
||||||
|
def apple_compiler?
|
||||||
|
false
|
||||||
|
end
|
||||||
|
|
||||||
|
def compatible_with?(other)
|
||||||
|
super &&
|
||||||
|
!other.apple_compiler? &&
|
||||||
|
compiler.to_s[4..6] == other.compiler.to_s[4..6]
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -159,7 +159,7 @@ class FormulaInstaller
|
|||||||
@poured_bottle = true
|
@poured_bottle = true
|
||||||
|
|
||||||
stdlibs = Keg.new(f.prefix).detect_cxx_stdlibs
|
stdlibs = Keg.new(f.prefix).detect_cxx_stdlibs
|
||||||
stdlib_in_use = CxxStdlib.new(stdlibs.first, MacOS.default_compiler)
|
stdlib_in_use = CxxStdlib.create(stdlibs.first, MacOS.default_compiler)
|
||||||
begin
|
begin
|
||||||
stdlib_in_use.check_dependencies(f, f.recursive_dependencies)
|
stdlib_in_use.check_dependencies(f, f.recursive_dependencies)
|
||||||
rescue IncompatibleCxxStdlibs => e
|
rescue IncompatibleCxxStdlibs => e
|
||||||
|
|||||||
@ -119,7 +119,7 @@ class Tab < OpenStruct
|
|||||||
# Older tabs won't have these values, so provide sensible defaults
|
# Older tabs won't have these values, so provide sensible defaults
|
||||||
lib = stdlib.to_sym if stdlib
|
lib = stdlib.to_sym if stdlib
|
||||||
cc = compiler || MacOS.default_compiler
|
cc = compiler || MacOS.default_compiler
|
||||||
CxxStdlib.new(lib, cc.to_sym)
|
CxxStdlib.create(lib, cc.to_sym)
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_json
|
def to_json
|
||||||
|
|||||||
@ -5,14 +5,14 @@ require 'cxxstdlib'
|
|||||||
|
|
||||||
class CxxStdlibTests < Homebrew::TestCase
|
class CxxStdlibTests < Homebrew::TestCase
|
||||||
def setup
|
def setup
|
||||||
@clang = CxxStdlib.new(:libstdcxx, :clang)
|
@clang = CxxStdlib.create(:libstdcxx, :clang)
|
||||||
@gcc = CxxStdlib.new(:libstdcxx, :gcc)
|
@gcc = CxxStdlib.create(:libstdcxx, :gcc)
|
||||||
@llvm = CxxStdlib.new(:libstdcxx, :llvm)
|
@llvm = CxxStdlib.create(:libstdcxx, :llvm)
|
||||||
@gcc4 = CxxStdlib.new(:libstdcxx, :gcc_4_0)
|
@gcc4 = CxxStdlib.create(:libstdcxx, :gcc_4_0)
|
||||||
@gcc48 = CxxStdlib.new(:libstdcxx, 'gcc-4.8')
|
@gcc48 = CxxStdlib.create(:libstdcxx, 'gcc-4.8')
|
||||||
@gcc49 = CxxStdlib.new(:libstdcxx, 'gcc-4.9')
|
@gcc49 = CxxStdlib.create(:libstdcxx, 'gcc-4.9')
|
||||||
@lcxx = CxxStdlib.new(:libcxx, :clang)
|
@lcxx = CxxStdlib.create(:libcxx, :clang)
|
||||||
@purec = CxxStdlib.new(nil, :clang)
|
@purec = CxxStdlib.create(nil, :clang)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_apple_libstdcxx_intercompatibility
|
def test_apple_libstdcxx_intercompatibility
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user