
For most formulae, the bottles need a minimum libstdc++ rather than a minimum GCC version. This is particularly important when building on Ubuntu where the default compiler version is older than libstdc++. So, checking the host libstdc++ version is a more accurate way to determine whether brew GCC is needed at runtime. This can be improved in the future to check symbol versions (e.g. GLIBCXX, CXXABI, GLIBC) which can allow some bottles to be installed even with older glibc/libstdc++.
128 lines
4.2 KiB
Ruby
128 lines
4.2 KiB
Ruby
# typed: strict
|
|
# frozen_string_literal: true
|
|
|
|
require "os/linux/ld"
|
|
require "os/linux/libstdcxx"
|
|
require "utils/output"
|
|
|
|
module OS
|
|
module Linux
|
|
module Install
|
|
module ClassMethods
|
|
# We link GCC runtime libraries that are not specifically used for Fortran,
|
|
# which are linked by the GCC formula. We only use the versioned shared libraries
|
|
# as the other shared and static libraries are only used at build time where
|
|
# GCC can find its own libraries.
|
|
GCC_RUNTIME_LIBS = T.let(%W[
|
|
libatomic.so.1
|
|
libgcc_s.so.1
|
|
libgomp.so.1
|
|
#{OS::Linux::Libstdcxx::SONAME}
|
|
].freeze, T::Array[String])
|
|
|
|
sig { params(all_fatal: T::Boolean).void }
|
|
def perform_preinstall_checks(all_fatal: false)
|
|
super
|
|
symlink_ld_so
|
|
setup_preferred_gcc_libs
|
|
end
|
|
|
|
sig { void }
|
|
def global_post_install
|
|
super
|
|
symlink_ld_so
|
|
setup_preferred_gcc_libs
|
|
end
|
|
|
|
sig { void }
|
|
def check_cpu
|
|
return if ::Hardware::CPU.intel? && ::Hardware::CPU.is_64_bit?
|
|
return if ::Hardware::CPU.arm?
|
|
|
|
message = "Sorry, Homebrew does not support your computer's CPU architecture!"
|
|
if ::Hardware::CPU.ppc64le?
|
|
message += <<~EOS
|
|
For OpenPOWER Linux (PPC64LE) support, see:
|
|
#{Formatter.url("https://github.com/homebrew-ppc64le/brew")}
|
|
EOS
|
|
end
|
|
::Kernel.abort message
|
|
end
|
|
|
|
sig { void }
|
|
def symlink_ld_so
|
|
brew_ld_so = HOMEBREW_PREFIX/"lib/ld.so"
|
|
|
|
ld_so = HOMEBREW_PREFIX/"opt/glibc/bin/ld.so"
|
|
unless ld_so.readable?
|
|
ld_so = OS::Linux::Ld.system_ld_so
|
|
if ld_so.blank?
|
|
::Kernel.raise "Unable to locate the system's dynamic linker" unless brew_ld_so.readable?
|
|
|
|
return
|
|
end
|
|
end
|
|
|
|
return if brew_ld_so.readable? && (brew_ld_so.readlink == ld_so)
|
|
|
|
FileUtils.mkdir_p HOMEBREW_PREFIX/"lib"
|
|
FileUtils.ln_sf ld_so, brew_ld_so
|
|
end
|
|
|
|
sig { void }
|
|
def setup_preferred_gcc_libs
|
|
gcc_opt_prefix = HOMEBREW_PREFIX/"opt/#{OS::LINUX_PREFERRED_GCC_RUNTIME_FORMULA}"
|
|
glibc_installed = (HOMEBREW_PREFIX/"opt/glibc/bin/ld.so").readable?
|
|
|
|
return unless gcc_opt_prefix.readable?
|
|
|
|
if glibc_installed
|
|
ld_so_conf_d = HOMEBREW_PREFIX/"etc/ld.so.conf.d"
|
|
unless ld_so_conf_d.exist?
|
|
ld_so_conf_d.mkpath
|
|
FileUtils.chmod "go-w", ld_so_conf_d
|
|
end
|
|
|
|
# Add gcc to ld search paths
|
|
ld_gcc_conf = ld_so_conf_d/"50-homebrew-preferred-gcc.conf"
|
|
ld_gcc_conf_content = <<~EOS
|
|
# This file is generated by Homebrew. Do not modify.
|
|
#{gcc_opt_prefix}/lib/gcc/current
|
|
EOS
|
|
|
|
if !ld_gcc_conf.exist? || (ld_gcc_conf.read != ld_gcc_conf_content)
|
|
ld_gcc_conf.atomic_write ld_gcc_conf_content
|
|
FileUtils.chmod "u=rw,go-wx", ld_gcc_conf
|
|
|
|
FileUtils.rm_f HOMEBREW_PREFIX/"etc/ld.so.cache"
|
|
::Kernel.system HOMEBREW_PREFIX/"opt/glibc/sbin/ldconfig"
|
|
end
|
|
else
|
|
Utils::Output.odie "#{HOMEBREW_PREFIX}/lib does not exist!" unless (HOMEBREW_PREFIX/"lib").readable?
|
|
end
|
|
|
|
GCC_RUNTIME_LIBS.each do |library|
|
|
gcc_library_symlink = HOMEBREW_PREFIX/"lib/#{library}"
|
|
|
|
if glibc_installed
|
|
# Remove legacy symlinks
|
|
FileUtils.rm gcc_library_symlink if gcc_library_symlink.symlink?
|
|
else
|
|
gcc_library = gcc_opt_prefix/"lib/gcc/current/#{library}"
|
|
# Skip if the link target doesn't exist.
|
|
next unless gcc_library.readable?
|
|
|
|
# Also skip if the symlink already exists.
|
|
next if gcc_library_symlink.readable? && (gcc_library_symlink.readlink == gcc_library)
|
|
|
|
FileUtils.ln_sf gcc_library, gcc_library_symlink
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
Homebrew::Install.singleton_class.prepend(OS::Linux::Install::ClassMethods)
|