diff --git a/.gitignore b/.gitignore index f5fa53701f..962dfd140e 100644 --- a/.gitignore +++ b/.gitignore @@ -129,9 +129,6 @@ **/vendor/bundle/ruby/*/gems/simplecov-*/ **/vendor/bundle/ruby/*/gems/simplecov-cobertura-*/ **/vendor/bundle/ruby/*/gems/simplecov-html-*/ -**/vendor/bundle/ruby/*/gems/sorbet-*/ -**/vendor/bundle/ruby/*/gems/sorbet-runtime-*/ -**/vendor/bundle/ruby/*/gems/tapioca-*/ **/vendor/bundle/ruby/*/gems/term-ansicolor-*/ **/vendor/bundle/ruby/*/gems/thor-*/ **/vendor/bundle/ruby/*/gems/tins-*/ @@ -140,6 +137,14 @@ **/vendor/bundle/ruby/*/gems/unicode-display_width-*/ **/vendor/bundle/ruby/*/gems/webrobots-*/ +# Ignore conditional dependencies we don't wish to vendor +**/vendor/bundle/ruby/*/gems/bindata-*/ +**/vendor/bundle/ruby/*/gems/elftools-*/ +**/vendor/bundle/ruby/*/gems/patchelf-*/ +**/vendor/bundle/ruby/*/gems/sorbet-*/ +**/vendor/bundle/ruby/*/gems/sorbet-runtime-*/ +**/vendor/bundle/ruby/*/gems/tapioca-*/ + # Ignore `bin` contents (again). /bin diff --git a/Library/Homebrew/Gemfile b/Library/Homebrew/Gemfile index 3024597c27..657bf5bd54 100644 --- a/Library/Homebrew/Gemfile +++ b/Library/Homebrew/Gemfile @@ -23,6 +23,7 @@ end gem "activesupport" gem "concurrent-ruby" gem "mechanize" +gem "patchelf" if ENV["HOMEBREW_PATCHELF_RB"] gem "plist" gem "rubocop-performance" gem "rubocop-rspec" diff --git a/Library/Homebrew/os/linux/elf.rb b/Library/Homebrew/os/linux/elf.rb index 11603dee71..6e7eda8d3a 100644 --- a/Library/Homebrew/os/linux/elf.rb +++ b/Library/Homebrew/os/linux/elf.rb @@ -74,7 +74,14 @@ module ELFShim @with_interpreter = if binary_executable? true elsif dylib? - if which "readelf" + if HOMEBREW_PATCHELF_RB + begin + patchelf_patcher.interpreter.present? + rescue PatchELF::PatchError => e + opoo e + false + end + elsif which "readelf" Utils.popen_read("readelf", "-l", to_path).include?(" INTERP ") elsif which "file" Utils.popen_read("file", "-L", "-b", to_path).include?(" interpreter ") @@ -89,7 +96,9 @@ module ELFShim def dynamic_elf? return @dynamic_elf if defined? @dynamic_elf - @dynamic_elf = if which "readelf" + @dynamic_elf = if HOMEBREW_PATCHELF_RB + patchelf_patcher.instance_variable_get(:@elf).segment_by_type(:DYNAMIC).present? + elsif which "readelf" Utils.popen_read("readelf", "-l", to_path).include?(" DYNAMIC ") elsif which "file" !Utils.popen_read("file", "-L", "-b", to_path)[/dynamic|shared/].nil? @@ -127,7 +136,9 @@ module ELFShim private def needed_libraries(path) - if DevelopmentTools.locate "readelf" + if HOMEBREW_PATCHELF_RB + needed_libraries_using_patchelf_rb path + elsif DevelopmentTools.locate "readelf" needed_libraries_using_readelf path elsif DevelopmentTools.locate "patchelf" needed_libraries_using_patchelf path @@ -138,6 +149,25 @@ module ELFShim end end + def needed_libraries_using_patchelf_rb(path) + patcher = path.patchelf_patcher + return [nil, []] unless patcher + + soname = begin + patcher.soname + rescue PatchELF::PatchError => e + opoo e unless e.to_s.start_with? "Entry DT_SONAME not found, not a shared library?" + nil + end + needed = begin + patcher.needed + rescue PatchELF::PatchError => e + opoo e + [] + end + [soname, needed] + end + def needed_libraries_using_patchelf(path) return [nil, []] unless path.dynamic_elf? @@ -172,6 +202,16 @@ module ELFShim end end + def patchelf_patcher + return unless HOMEBREW_PATCHELF_RB + + @patchelf_patcher ||= begin + Homebrew.install_bundler_gems! + require "patchelf" + PatchELF::Patcher.new to_s, logging: false + end + end + def metadata @metadata ||= Metadata.new(self) end diff --git a/Library/Homebrew/os/linux/global.rb b/Library/Homebrew/os/linux/global.rb index e0b8724930..fb74e0afa3 100644 --- a/Library/Homebrew/os/linux/global.rb +++ b/Library/Homebrew/os/linux/global.rb @@ -1,5 +1,8 @@ # frozen_string_literal: true +# enables experimental readelf.rb, patchelf support. +HOMEBREW_PATCHELF_RB = ENV["HOMEBREW_PATCHELF_RB"].present?.freeze + module Homebrew DEFAULT_PREFIX ||= if Homebrew::EnvConfig.force_homebrew_on_linux? HOMEBREW_DEFAULT_PREFIX