Cleanup use of CxxStdlib
- remove usage on macOS as we don't care about it there - don't error out on incompatibility but still store stdlib on Linux - remove (now) unused methods
This commit is contained in:
parent
f266acff2d
commit
04abc51d1f
@ -8,7 +8,6 @@ old_trap = trap("INT") { exit! 130 }
|
|||||||
|
|
||||||
require_relative "global"
|
require_relative "global"
|
||||||
require "build_options"
|
require "build_options"
|
||||||
require "cxxstdlib"
|
|
||||||
require "keg"
|
require "keg"
|
||||||
require "extend/ENV"
|
require "extend/ENV"
|
||||||
require "debrew"
|
require "debrew"
|
||||||
@ -174,7 +173,7 @@ class Build
|
|||||||
"#{formula.full_name} #{formula.build.used_options.sort.join(" ")}".strip
|
"#{formula.full_name} #{formula.build.used_options.sort.join(" ")}".strip
|
||||||
formula.install
|
formula.install
|
||||||
|
|
||||||
stdlibs = detect_stdlibs(ENV.compiler)
|
stdlibs = detect_stdlibs
|
||||||
tab = Tab.create(formula, ENV.compiler, stdlibs.first)
|
tab = Tab.create(formula, ENV.compiler, stdlibs.first)
|
||||||
tab.write
|
tab.write
|
||||||
|
|
||||||
@ -186,9 +185,8 @@ class Build
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def detect_stdlibs(compiler)
|
def detect_stdlibs
|
||||||
keg = Keg.new(formula.prefix)
|
keg = Keg.new(formula.prefix)
|
||||||
CxxStdlib.check_compatibility(formula, deps, keg, compiler)
|
|
||||||
|
|
||||||
# The stdlib recorded in the install receipt is used during dependency
|
# The stdlib recorded in the install receipt is used during dependency
|
||||||
# compatibility checks, so we only care about the stdlib that libraries
|
# compatibility checks, so we only care about the stdlib that libraries
|
||||||
|
|||||||
@ -22,52 +22,14 @@ class CxxStdlib
|
|||||||
def self.create(type, compiler)
|
def self.create(type, compiler)
|
||||||
raise ArgumentError, "Invalid C++ stdlib type: #{type}" if type && [:libstdcxx, :libcxx].exclude?(type)
|
raise ArgumentError, "Invalid C++ stdlib type: #{type}" if type && [:libstdcxx, :libcxx].exclude?(type)
|
||||||
|
|
||||||
apple_compiler = !compiler.to_s.match?(GNU_GCC_REGEXP)
|
CxxStdlib.new(type, compiler)
|
||||||
CxxStdlib.new(type, compiler, apple_compiler)
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.check_compatibility(formula, deps, keg, compiler)
|
|
||||||
return if formula.skip_cxxstdlib_check?
|
|
||||||
|
|
||||||
stdlib = create(keg.detect_cxx_stdlibs.first, compiler)
|
|
||||||
|
|
||||||
begin
|
|
||||||
stdlib.check_dependencies(formula, deps)
|
|
||||||
rescue CompatibilityError => e
|
|
||||||
opoo e.message
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
attr_reader :type, :compiler
|
attr_reader :type, :compiler
|
||||||
|
|
||||||
def initialize(type, compiler, apple_compiler)
|
def initialize(type, compiler)
|
||||||
@type = type
|
@type = type
|
||||||
@compiler = compiler.to_sym
|
@compiler = compiler.to_sym
|
||||||
@apple_compiler = apple_compiler
|
|
||||||
end
|
|
||||||
|
|
||||||
# If either package doesn't use C++, all is well.
|
|
||||||
# libstdc++ and libc++ aren't ever intercompatible.
|
|
||||||
# libstdc++ is compatible across Apple compilers, but
|
|
||||||
# not between Apple and GNU compilers, nor between GNU compiler versions.
|
|
||||||
def compatible_with?(other)
|
|
||||||
return true if type.nil? || other.type.nil?
|
|
||||||
|
|
||||||
return false unless type == other.type
|
|
||||||
|
|
||||||
apple_compiler? && other.apple_compiler? ||
|
|
||||||
!other.apple_compiler? && compiler.to_s[4..6] == other.compiler.to_s[4..6]
|
|
||||||
end
|
|
||||||
|
|
||||||
def check_dependencies(formula, deps)
|
|
||||||
deps.each do |dep|
|
|
||||||
# Software is unlikely to link against libraries from build-time deps, so
|
|
||||||
# it doesn't matter if they link against different C++ stdlibs.
|
|
||||||
next if dep.build?
|
|
||||||
|
|
||||||
dep_stdlib = Tab.for_formula(dep.to_formula).cxxstdlib
|
|
||||||
raise CompatibilityError.new(formula, dep, dep_stdlib) unless compatible_with? dep_stdlib
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def type_string
|
def type_string
|
||||||
@ -78,8 +40,4 @@ class CxxStdlib
|
|||||||
def inspect
|
def inspect
|
||||||
"#<#{self.class.name}: #{compiler} #{type}>"
|
"#<#{self.class.name}: #{compiler} #{type}>"
|
||||||
end
|
end
|
||||||
|
|
||||||
def apple_compiler?
|
|
||||||
@apple_compiler
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|||||||
@ -16,7 +16,7 @@ class Keg
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
undef relocate_dynamic_linkage, detect_cxx_stdlibs
|
undef relocate_dynamic_linkage
|
||||||
|
|
||||||
def relocate_dynamic_linkage(relocation)
|
def relocate_dynamic_linkage(relocation)
|
||||||
mach_o_files.each do |file|
|
mach_o_files.each do |file|
|
||||||
@ -39,25 +39,6 @@ class Keg
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Detects the C++ dynamic libraries in-place, scanning the dynamic links
|
|
||||||
# of the files within the keg.
|
|
||||||
# Note that this doesn't attempt to distinguish between libstdc++ versions,
|
|
||||||
# for instance between Apple libstdc++ and GNU libstdc++.
|
|
||||||
def detect_cxx_stdlibs(options = {})
|
|
||||||
skip_executables = options.fetch(:skip_executables, false)
|
|
||||||
results = Set.new
|
|
||||||
|
|
||||||
mach_o_files.each do |file|
|
|
||||||
next if file.mach_o_executable? && skip_executables
|
|
||||||
|
|
||||||
dylibs = file.dynamically_linked_libraries
|
|
||||||
results << :libcxx unless dylibs.grep(/libc\+\+.+\.dylib/).empty?
|
|
||||||
results << :libstdcxx unless dylibs.grep(/libstdc\+\+.+\.dylib/).empty?
|
|
||||||
end
|
|
||||||
|
|
||||||
results.to_a
|
|
||||||
end
|
|
||||||
|
|
||||||
def fix_dynamic_linkage
|
def fix_dynamic_linkage
|
||||||
mach_o_files.each do |file|
|
mach_o_files.each do |file|
|
||||||
file.ensure_writable do
|
file.ensure_writable do
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
# typed: false
|
# typed: false
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require "cxxstdlib"
|
|
||||||
require "formula"
|
require "formula"
|
||||||
require "keg"
|
require "keg"
|
||||||
require "tab"
|
require "tab"
|
||||||
@ -1137,13 +1136,6 @@ class FormulaInstaller
|
|||||||
skip_linkage = formula.bottle_specification.skip_relocation?
|
skip_linkage = formula.bottle_specification.skip_relocation?
|
||||||
keg.replace_placeholders_with_locations tab.changed_files, skip_linkage: skip_linkage
|
keg.replace_placeholders_with_locations tab.changed_files, skip_linkage: skip_linkage
|
||||||
|
|
||||||
unless ignore_deps?
|
|
||||||
CxxStdlib.check_compatibility(
|
|
||||||
formula, formula.recursive_dependencies,
|
|
||||||
Keg.new(formula.prefix), tab.compiler
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
# fill in missing/outdated parts of the tab
|
# fill in missing/outdated parts of the tab
|
||||||
# keep in sync with Tab#to_bottle_json
|
# keep in sync with Tab#to_bottle_json
|
||||||
tab.used_options = []
|
tab.used_options = []
|
||||||
|
|||||||
@ -6,50 +6,7 @@ require "cxxstdlib"
|
|||||||
|
|
||||||
describe CxxStdlib do
|
describe CxxStdlib do
|
||||||
let(:clang) { described_class.create(:libstdcxx, :clang) }
|
let(:clang) { described_class.create(:libstdcxx, :clang) }
|
||||||
let(:gcc6) { described_class.create(:libstdcxx, "gcc-6") }
|
|
||||||
let(:gcc7) { described_class.create(:libstdcxx, "gcc-7") }
|
|
||||||
let(:lcxx) { described_class.create(:libcxx, :clang) }
|
let(:lcxx) { described_class.create(:libcxx, :clang) }
|
||||||
let(:purec) { described_class.create(nil, :clang) }
|
|
||||||
|
|
||||||
describe "#compatible_with?" do
|
|
||||||
specify "compatibility with itself" do
|
|
||||||
expect(gcc7).to be_compatible_with(gcc7)
|
|
||||||
expect(clang).to be_compatible_with(clang)
|
|
||||||
end
|
|
||||||
|
|
||||||
specify "Apple/GNU libstdcxx incompatibility" do
|
|
||||||
expect(clang).not_to be_compatible_with(gcc7)
|
|
||||||
expect(gcc7).not_to be_compatible_with(clang)
|
|
||||||
end
|
|
||||||
|
|
||||||
specify "GNU cross-version incompatibility" do
|
|
||||||
expect(gcc6).not_to be_compatible_with(gcc7)
|
|
||||||
expect(gcc7).not_to be_compatible_with(gcc6)
|
|
||||||
end
|
|
||||||
|
|
||||||
specify "libstdcxx and libcxx incompatibility" do
|
|
||||||
expect(clang).not_to be_compatible_with(lcxx)
|
|
||||||
expect(lcxx).not_to be_compatible_with(clang)
|
|
||||||
end
|
|
||||||
|
|
||||||
specify "compatibility for non-cxx software" do
|
|
||||||
expect(purec).to be_compatible_with(clang)
|
|
||||||
expect(clang).to be_compatible_with(purec)
|
|
||||||
expect(purec).to be_compatible_with(purec)
|
|
||||||
expect(purec).to be_compatible_with(gcc7)
|
|
||||||
expect(gcc7).to be_compatible_with(purec)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe "#apple_compiler?" do
|
|
||||||
it "returns true for Apple compilers" do
|
|
||||||
expect(clang).to be_an_apple_compiler
|
|
||||||
end
|
|
||||||
|
|
||||||
it "returns false for non-Apple compilers" do
|
|
||||||
expect(gcc7).not_to be_an_apple_compiler
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe "#type_string" do
|
describe "#type_string" do
|
||||||
specify "formatting" do
|
specify "formatting" do
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user