2018-08-21 18:01:34 -04:00
|
|
|
# Require the main spec_helper.rb at the end to let `ruby ...spec.rb` work
|
2017-06-15 08:48:52 -04:00
|
|
|
|
|
|
|
# MRI magic to use built but not installed ruby
|
2017-05-28 12:40:12 -04:00
|
|
|
$extmk = false
|
2017-05-07 08:04:49 -04:00
|
|
|
|
|
|
|
require 'rbconfig'
|
|
|
|
|
2017-06-15 08:48:52 -04:00
|
|
|
OBJDIR ||= File.expand_path("../../../ext/#{RUBY_ENGINE}/#{RUBY_VERSION}", __FILE__)
|
2017-05-07 08:04:49 -04:00
|
|
|
|
|
|
|
def object_path
|
2018-08-21 18:01:34 -04:00
|
|
|
mkdir_p(OBJDIR)
|
2017-05-07 08:04:49 -04:00
|
|
|
OBJDIR
|
|
|
|
end
|
|
|
|
|
|
|
|
def compile_extension(name)
|
2017-06-15 08:48:52 -04:00
|
|
|
debug = false
|
|
|
|
run_mkmf_in_process = RUBY_ENGINE == 'truffleruby'
|
2017-05-07 08:04:49 -04:00
|
|
|
|
2018-09-25 06:41:16 -04:00
|
|
|
core_ext_dir = File.expand_path("../ext", __FILE__)
|
|
|
|
|
|
|
|
spec_caller_location = caller_locations.find { |c| c.path.end_with?('_spec.rb') }
|
|
|
|
spec_file_path = spec_caller_location.path
|
|
|
|
spec_ext_dir = File.expand_path("../ext", spec_file_path)
|
|
|
|
|
2017-06-15 08:48:52 -04:00
|
|
|
ext = "#{name}_spec"
|
|
|
|
lib = "#{object_path}/#{ext}.#{RbConfig::CONFIG['DLEXT']}"
|
|
|
|
ruby_header = "#{RbConfig::CONFIG['rubyhdrdir']}/ruby.h"
|
2018-09-25 06:41:16 -04:00
|
|
|
|
|
|
|
if RbConfig::CONFIG["ENABLE_SHARED"] == "yes"
|
|
|
|
if PlatformGuard.windows?
|
|
|
|
libruby_so = "#{RbConfig::CONFIG['bindir']}/#{RbConfig::CONFIG['LIBRUBY_SO']}"
|
|
|
|
else
|
|
|
|
libruby_so = "#{RbConfig::CONFIG['libdir']}/#{RbConfig::CONFIG['LIBRUBY_SO']}"
|
|
|
|
end
|
2018-09-03 23:41:44 -04:00
|
|
|
end
|
2018-09-25 06:41:16 -04:00
|
|
|
|
2017-12-26 20:58:18 -05:00
|
|
|
begin
|
|
|
|
mtime = File.mtime(lib)
|
|
|
|
rescue Errno::ENOENT
|
|
|
|
# not found, then compile
|
|
|
|
else
|
|
|
|
case # if lib is older than headers, source or libruby, then recompile
|
2018-09-25 06:41:16 -04:00
|
|
|
when mtime <= File.mtime("#{core_ext_dir}/rubyspec.h")
|
|
|
|
when mtime <= File.mtime("#{spec_ext_dir}/#{ext}.c")
|
2017-12-26 20:58:18 -05:00
|
|
|
when mtime <= File.mtime(ruby_header)
|
2018-09-25 06:41:16 -04:00
|
|
|
when libruby_so && mtime <= File.mtime(libruby_so)
|
2017-12-26 20:58:18 -05:00
|
|
|
else
|
|
|
|
return lib # up-to-date
|
|
|
|
end
|
|
|
|
end
|
2017-05-07 08:04:49 -04:00
|
|
|
|
2017-05-27 17:55:02 -04:00
|
|
|
# Copy needed source files to tmpdir
|
|
|
|
tmpdir = tmp("cext_#{name}")
|
2017-06-15 08:48:52 -04:00
|
|
|
Dir.mkdir(tmpdir)
|
2017-05-07 08:04:49 -04:00
|
|
|
begin
|
2018-09-25 06:41:16 -04:00
|
|
|
["#{core_ext_dir}/rubyspec.h", "#{spec_ext_dir}/#{ext}.c"].each do |file|
|
|
|
|
cp file, "#{tmpdir}/#{File.basename(file)}"
|
2017-05-27 17:55:02 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
Dir.chdir(tmpdir) do
|
2017-06-15 08:48:52 -04:00
|
|
|
if run_mkmf_in_process
|
|
|
|
required = require 'mkmf'
|
|
|
|
# Reinitialize mkmf if already required
|
|
|
|
init_mkmf unless required
|
|
|
|
create_makefile(ext, tmpdir)
|
|
|
|
else
|
|
|
|
File.write("extconf.rb", "require 'mkmf'\n" +
|
|
|
|
"$ruby = ENV.values_at('RUBY_EXE', 'RUBY_FLAGS').join(' ')\n" +
|
|
|
|
# MRI magic to consider building non-bundled extensions
|
|
|
|
"$extout = nil\n" +
|
|
|
|
"create_makefile(#{ext.inspect})\n")
|
|
|
|
output = ruby_exe("extconf.rb")
|
|
|
|
raise "extconf failed:\n#{output}" unless $?.success?
|
|
|
|
$stderr.puts output if debug
|
2017-05-28 12:29:04 -04:00
|
|
|
end
|
2017-06-15 08:48:52 -04:00
|
|
|
|
|
|
|
# Do not capture stderr as we want to show compiler warnings
|
2017-09-20 15:45:19 -04:00
|
|
|
make, opts = setup_make
|
2017-08-02 20:53:25 -04:00
|
|
|
output = IO.popen([make, "V=1", "DESTDIR=", opts], &:read)
|
2017-06-15 08:48:52 -04:00
|
|
|
raise "#{make} failed:\n#{output}" unless $?.success?
|
|
|
|
$stderr.puts output if debug
|
|
|
|
|
|
|
|
cp File.basename(lib), lib
|
2017-05-07 08:04:49 -04:00
|
|
|
end
|
|
|
|
ensure
|
2017-05-27 17:55:02 -04:00
|
|
|
rm_r tmpdir
|
2017-05-07 08:04:49 -04:00
|
|
|
end
|
2017-05-27 17:55:02 -04:00
|
|
|
|
2017-06-15 08:48:52 -04:00
|
|
|
File.chmod(0755, lib)
|
2017-05-27 17:55:02 -04:00
|
|
|
lib
|
2017-05-07 08:04:49 -04:00
|
|
|
end
|
|
|
|
|
2017-09-20 15:45:19 -04:00
|
|
|
def setup_make
|
|
|
|
make = ENV['MAKE']
|
|
|
|
make ||= (RbConfig::CONFIG['host_os'].include?("mswin") ? "nmake" : "make")
|
|
|
|
make_flags = ENV["MAKEFLAGS"] || ''
|
|
|
|
|
|
|
|
# suppress logo of nmake.exe to stderr
|
|
|
|
if File.basename(make, ".*").downcase == "nmake" and !make_flags.include?("l")
|
|
|
|
ENV["MAKEFLAGS"] = "l#{make_flags}"
|
|
|
|
end
|
|
|
|
|
|
|
|
opts = {}
|
|
|
|
if /(?:\A|\s)--jobserver-(?:auth|fds)=(\d+),(\d+)/ =~ make_flags
|
|
|
|
begin
|
|
|
|
r = IO.for_fd($1.to_i(10), "rb", autoclose: false)
|
|
|
|
w = IO.for_fd($2.to_i(10), "wb", autoclose: false)
|
|
|
|
rescue Errno::EBADF
|
|
|
|
else
|
|
|
|
opts[r] = r
|
|
|
|
opts[w] = w
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
[make, opts]
|
|
|
|
end
|
|
|
|
|
2017-05-07 08:04:49 -04:00
|
|
|
def load_extension(name)
|
|
|
|
require compile_extension(name)
|
2018-08-21 18:01:34 -04:00
|
|
|
rescue LoadError => e
|
|
|
|
if %r{/usr/sbin/execerror ruby "\(ld 3 1 main ([/a-zA-Z0-9_\-.]+_spec\.so)"} =~ e.message
|
2017-05-07 08:04:49 -04:00
|
|
|
system('/usr/sbin/execerror', "#{RbConfig::CONFIG["bindir"]}/ruby", "(ld 3 1 main #{$1}")
|
|
|
|
end
|
|
|
|
raise
|
|
|
|
end
|
|
|
|
|
|
|
|
# Constants
|
|
|
|
CAPI_SIZEOF_LONG = [0].pack('l!').size
|
2018-08-21 18:01:34 -04:00
|
|
|
|
|
|
|
# Require the main spec_helper.rb only here so load_extension() is defined
|
|
|
|
# when running specs with `ruby ...spec.rb`
|
|
|
|
require_relative '../../spec_helper'
|