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 "build_options"
 | 
			
		||||
require "cxxstdlib"
 | 
			
		||||
require "keg"
 | 
			
		||||
require "extend/ENV"
 | 
			
		||||
require "debrew"
 | 
			
		||||
@ -174,7 +173,7 @@ class Build
 | 
			
		||||
            "#{formula.full_name} #{formula.build.used_options.sort.join(" ")}".strip
 | 
			
		||||
          formula.install
 | 
			
		||||
 | 
			
		||||
          stdlibs = detect_stdlibs(ENV.compiler)
 | 
			
		||||
          stdlibs = detect_stdlibs
 | 
			
		||||
          tab = Tab.create(formula, ENV.compiler, stdlibs.first)
 | 
			
		||||
          tab.write
 | 
			
		||||
 | 
			
		||||
@ -186,9 +185,8 @@ class Build
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def detect_stdlibs(compiler)
 | 
			
		||||
  def detect_stdlibs
 | 
			
		||||
    keg = Keg.new(formula.prefix)
 | 
			
		||||
    CxxStdlib.check_compatibility(formula, deps, keg, compiler)
 | 
			
		||||
 | 
			
		||||
    # The stdlib recorded in the install receipt is used during dependency
 | 
			
		||||
    # compatibility checks, so we only care about the stdlib that libraries
 | 
			
		||||
 | 
			
		||||
@ -22,52 +22,14 @@ class CxxStdlib
 | 
			
		||||
  def self.create(type, compiler)
 | 
			
		||||
    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, 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
 | 
			
		||||
    CxxStdlib.new(type, compiler)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  attr_reader :type, :compiler
 | 
			
		||||
 | 
			
		||||
  def initialize(type, compiler, apple_compiler)
 | 
			
		||||
  def initialize(type, compiler)
 | 
			
		||||
    @type = type
 | 
			
		||||
    @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
 | 
			
		||||
 | 
			
		||||
  def type_string
 | 
			
		||||
@ -78,8 +40,4 @@ class CxxStdlib
 | 
			
		||||
  def inspect
 | 
			
		||||
    "#<#{self.class.name}: #{compiler} #{type}>"
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def apple_compiler?
 | 
			
		||||
    @apple_compiler
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
@ -16,7 +16,7 @@ class Keg
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  undef relocate_dynamic_linkage, detect_cxx_stdlibs
 | 
			
		||||
  undef relocate_dynamic_linkage
 | 
			
		||||
 | 
			
		||||
  def relocate_dynamic_linkage(relocation)
 | 
			
		||||
    mach_o_files.each do |file|
 | 
			
		||||
@ -39,25 +39,6 @@ class Keg
 | 
			
		||||
    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
 | 
			
		||||
    mach_o_files.each do |file|
 | 
			
		||||
      file.ensure_writable do
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,6 @@
 | 
			
		||||
# typed: false
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "cxxstdlib"
 | 
			
		||||
require "formula"
 | 
			
		||||
require "keg"
 | 
			
		||||
require "tab"
 | 
			
		||||
@ -1137,13 +1136,6 @@ class FormulaInstaller
 | 
			
		||||
    skip_linkage = formula.bottle_specification.skip_relocation?
 | 
			
		||||
    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
 | 
			
		||||
    # keep in sync with Tab#to_bottle_json
 | 
			
		||||
    tab.used_options = []
 | 
			
		||||
 | 
			
		||||
@ -6,50 +6,7 @@ require "cxxstdlib"
 | 
			
		||||
 | 
			
		||||
describe CxxStdlib do
 | 
			
		||||
  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(: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
 | 
			
		||||
    specify "formatting" do
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user