diff options
Diffstat (limited to 'lib/rubygems/ext')
-rw-r--r-- | lib/rubygems/ext/builder.rb | 45 | ||||
-rw-r--r-- | lib/rubygems/ext/cmake_builder.rb | 8 | ||||
-rw-r--r-- | lib/rubygems/ext/configure_builder.rb | 8 | ||||
-rw-r--r-- | lib/rubygems/ext/ext_conf_builder.rb | 33 | ||||
-rw-r--r-- | lib/rubygems/ext/rake_builder.rb | 6 |
5 files changed, 43 insertions, 57 deletions
diff --git a/lib/rubygems/ext/builder.rb b/lib/rubygems/ext/builder.rb index afc8cb0ee4..f6de6a50d7 100644 --- a/lib/rubygems/ext/builder.rb +++ b/lib/rubygems/ext/builder.rb @@ -10,14 +10,6 @@ require_relative '../user_interaction' class Gem::Ext::Builder include Gem::UserInteraction - ## - # The builder shells-out to run various commands after changing the - # directory. This means multiple installations cannot be allowed to build - # extensions in parallel as they may change each other's directories leading - # to broken extensions or failed installations. - - CHDIR_MUTEX = Mutex.new # :nodoc: - attr_accessor :build_args # :nodoc: def self.class_name @@ -25,8 +17,8 @@ class Gem::Ext::Builder $1.downcase end - def self.make(dest_path, results) - unless File.exist? 'Makefile' + def self.make(dest_path, results, make_dir = Dir.pwd) + unless File.exist? File.join(make_dir, 'Makefile') raise Gem::InstallError, 'Makefile not found' end @@ -44,32 +36,32 @@ class Gem::Ext::Builder cmd = [ make_program, destdir, - target + target, ].join(' ').rstrip begin - run(cmd, results, "make #{target}".rstrip) + run(cmd, results, "make #{target}".rstrip, make_dir) rescue Gem::InstallError raise unless target == 'clean' # ignore clean failure end end end - def self.run(command, results, command_name = nil) + def self.run(command, results, command_name = nil, dir = Dir.pwd) verbose = Gem.configuration.really_verbose begin rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], nil if verbose - puts("current directory: #{Dir.pwd}") + puts("current directory: #{dir}") p(command) end - results << "current directory: #{Dir.pwd}" + results << "current directory: #{dir}" results << (command.respond_to?(:shelljoin) ? command.shelljoin : command) require "open3" # Set $SOURCE_DATE_EPOCH for the subprocess. env = {'SOURCE_DATE_EPOCH' => Gem.source_date_epoch_string} - output, status = Open3.capture2e(env, *command) + output, status = Open3.capture2e(env, *command, :chdir => dir) if verbose puts output else @@ -161,22 +153,10 @@ EOF begin FileUtils.mkdir_p dest_path - CHDIR_MUTEX.synchronize do - pwd = Dir.getwd - Dir.chdir extension_dir - begin - results = builder.build(extension, dest_path, - results, @build_args, lib_dir) - - verbose { results.join("\n") } - ensure - begin - Dir.chdir pwd - rescue SystemCallError - Dir.chdir dest_path - end - end - end + results = builder.build(extension, dest_path, + results, @build_args, lib_dir, extension_dir) + + verbose { results.join("\n") } write_gem_make_out results.join "\n" rescue => e @@ -201,6 +181,7 @@ EOF dest_path = @spec.extension_dir + require "fileutils" FileUtils.rm_f @spec.gem_build_complete_path @spec.extensions.each do |extension| diff --git a/lib/rubygems/ext/cmake_builder.rb b/lib/rubygems/ext/cmake_builder.rb index 519372e742..2efec91f15 100644 --- a/lib/rubygems/ext/cmake_builder.rb +++ b/lib/rubygems/ext/cmake_builder.rb @@ -2,15 +2,15 @@ require_relative '../command' class Gem::Ext::CmakeBuilder < Gem::Ext::Builder - def self.build(extension, dest_path, results, args=[], lib_dir=nil) - unless File.exist?('Makefile') + def self.build(extension, dest_path, results, args=[], lib_dir=nil, cmake_dir=Dir.pwd) + unless File.exist?(File.join(cmake_dir, 'Makefile')) cmd = "cmake . -DCMAKE_INSTALL_PREFIX=#{dest_path}" cmd << " #{Gem::Command.build_args.join ' '}" unless Gem::Command.build_args.empty? - run cmd, results + run cmd, results, class_name, cmake_dir end - make dest_path, results + make dest_path, results, cmake_dir results end diff --git a/lib/rubygems/ext/configure_builder.rb b/lib/rubygems/ext/configure_builder.rb index 209e75fe8e..36a758989b 100644 --- a/lib/rubygems/ext/configure_builder.rb +++ b/lib/rubygems/ext/configure_builder.rb @@ -6,15 +6,15 @@ #++ class Gem::Ext::ConfigureBuilder < Gem::Ext::Builder - def self.build(extension, dest_path, results, args=[], lib_dir=nil) - unless File.exist?('Makefile') + def self.build(extension, dest_path, results, args=[], lib_dir=nil, configure_dir=Dir.pwd) + unless File.exist?(File.join(configure_dir, 'Makefile')) cmd = "sh ./configure --prefix=#{dest_path}" cmd << " #{args.join ' '}" unless args.empty? - run cmd, results + run cmd, results, class_name, configure_dir end - make dest_path, results + make dest_path, results, configure_dir results end diff --git a/lib/rubygems/ext/ext_conf_builder.rb b/lib/rubygems/ext/ext_conf_builder.rb index 305e1dcfb1..fede270417 100644 --- a/lib/rubygems/ext/ext_conf_builder.rb +++ b/lib/rubygems/ext/ext_conf_builder.rb @@ -8,11 +8,11 @@ require 'shellwords' class Gem::Ext::ExtConfBuilder < Gem::Ext::Builder - def self.build(extension, dest_path, results, args=[], lib_dir=nil) + def self.build(extension, dest_path, results, args=[], lib_dir=nil, extension_dir=Dir.pwd) require 'fileutils' require 'tempfile' - tmp_dest = Dir.mktmpdir(".gem.", ".") + tmp_dest = Dir.mktmpdir(".gem.", extension_dir) # Some versions of `mktmpdir` return absolute paths, which will break make # if the paths contain spaces. However, on Ruby 1.9.x on Windows, relative @@ -23,9 +23,9 @@ class Gem::Ext::ExtConfBuilder < Gem::Ext::Builder # spaces do not work. # # Details: https://github.com/rubygems/rubygems/issues/977#issuecomment-171544940 - tmp_dest = get_relative_path(tmp_dest) + tmp_dest = get_relative_path(tmp_dest, extension_dir) - Tempfile.open %w[siteconf .rb], "." do |siteconf| + Tempfile.open %w[siteconf .rb], extension_dir do |siteconf| siteconf.puts "require 'rbconfig'" siteconf.puts "dest_path = #{tmp_dest.dump}" %w[sitearchdir sitelibdir].each do |dir| @@ -38,19 +38,22 @@ class Gem::Ext::ExtConfBuilder < Gem::Ext::Builder destdir = ENV["DESTDIR"] begin + # workaround for https://github.com/oracle/truffleruby/issues/2115 + siteconf_path = RUBY_ENGINE == "truffleruby" ? siteconf.path.dup : siteconf.path cmd = Gem.ruby.shellsplit << "-I" << File.expand_path("../../..", __FILE__) << - "-r" << get_relative_path(siteconf.path) << File.basename(extension) + "-r" << get_relative_path(siteconf_path, extension_dir) << File.basename(extension) cmd.push(*args) begin - run(cmd, results) do |s, r| - if File.exist? 'mkmf.log' + run(cmd, results, class_name, extension_dir) do |s, r| + mkmf_log = File.join(extension_dir, 'mkmf.log') + if File.exist? mkmf_log unless s.success? r << "To see why this extension failed to compile, please check" \ " the mkmf.log which can be found here:\n" r << " " + File.join(dest_path, 'mkmf.log') + "\n" end - FileUtils.mv 'mkmf.log', dest_path + FileUtils.mv mkmf_log, dest_path end end siteconf.unlink @@ -58,18 +61,20 @@ class Gem::Ext::ExtConfBuilder < Gem::Ext::Builder ENV["DESTDIR"] = nil - make dest_path, results + make dest_path, results, extension_dir if tmp_dest + full_tmp_dest = File.join(extension_dir, tmp_dest) + # TODO remove in RubyGems 3 if Gem.install_extension_in_lib and lib_dir FileUtils.mkdir_p lib_dir - entries = Dir.entries(tmp_dest) - %w[. ..] - entries = entries.map {|entry| File.join tmp_dest, entry } + entries = Dir.entries(full_tmp_dest) - %w[. ..] + entries = entries.map {|entry| File.join full_tmp_dest, entry } FileUtils.cp_r entries, lib_dir, :remove_destination => true end - FileUtils::Entry_.new(tmp_dest).traverse do |ent| + FileUtils::Entry_.new(full_tmp_dest).traverse do |ent| destent = ent.class.new(dest_path, ent.rel) destent.exist? or FileUtils.mv(ent.path, destent.path) end @@ -87,8 +92,8 @@ class Gem::Ext::ExtConfBuilder < Gem::Ext::Builder private - def self.get_relative_path(path) - path[0..Dir.pwd.length - 1] = '.' if path.start_with?(Dir.pwd) + def self.get_relative_path(path, base) + path[0..base.length - 1] = '.' if path.start_with?(base) path end end diff --git a/lib/rubygems/ext/rake_builder.rb b/lib/rubygems/ext/rake_builder.rb index 53507090fe..34c3922f2f 100644 --- a/lib/rubygems/ext/rake_builder.rb +++ b/lib/rubygems/ext/rake_builder.rb @@ -8,9 +8,9 @@ require "shellwords" class Gem::Ext::RakeBuilder < Gem::Ext::Builder - def self.build(extension, dest_path, results, args=[], lib_dir=nil) + def self.build(extension, dest_path, results, args=[], lib_dir=nil, extension_dir=Dir.pwd) if File.basename(extension) =~ /mkrf_conf/i - run([Gem.ruby, File.basename(extension), *args], results) + run([Gem.ruby, File.basename(extension), *args], results, class_name, extension_dir) end rake = ENV['rake'] @@ -26,7 +26,7 @@ class Gem::Ext::RakeBuilder < Gem::Ext::Builder end rake_args = ["RUBYARCHDIR=#{dest_path}", "RUBYLIBDIR=#{dest_path}", *args] - run(rake + rake_args, results) + run(rake + rake_args, results, class_name, extension_dir) results end |