summaryrefslogtreecommitdiff
path: root/spec/rubyspec/optional/capi/spec_helper.rb
blob: 71b765de07650e99808e9f6867b1f01ce53f9356 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
require File.expand_path('../../../spec_helper', __FILE__)

# MRI magic to use built but not installed ruby
$extmk = false

require 'rbconfig'

OBJDIR ||= File.expand_path("../../../ext/#{RUBY_ENGINE}/#{RUBY_VERSION}", __FILE__)
mkdir_p(OBJDIR)

def extension_path
  File.expand_path("../ext", __FILE__)
end

def object_path
  OBJDIR
end

def compile_extension(name)
  debug = false
  run_mkmf_in_process = RUBY_ENGINE == 'truffleruby'

  ext = "#{name}_spec"
  lib = "#{object_path}/#{ext}.#{RbConfig::CONFIG['DLEXT']}"
  ruby_header = "#{RbConfig::CONFIG['rubyhdrdir']}/ruby.h"

  return lib if File.exist?(lib) and
                File.mtime(lib) > File.mtime("#{extension_path}/rubyspec.h") and
                File.mtime(lib) > File.mtime("#{extension_path}/#{ext}.c") and
                File.mtime(lib) > File.mtime(ruby_header) and
                true            # sentinel

  # Copy needed source files to tmpdir
  tmpdir = tmp("cext_#{name}")
  Dir.mkdir(tmpdir)
  begin
    ["rubyspec.h", "#{ext}.c"].each do |file|
      cp "#{extension_path}/#{file}", "#{tmpdir}/#{file}"
    end

    Dir.chdir(tmpdir) do
      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
      end

      make = RbConfig::CONFIG['host_os'].include?("mswin") ? "nmake" : "make"
      ENV.delete "MAKEFLAGS" # Fix make warning when invoked with -j in MRI

      # Do not capture stderr as we want to show compiler warnings
      output = `#{make} V=1`
      raise "#{make} failed:\n#{output}" unless $?.success?
      $stderr.puts output if debug

      cp File.basename(lib), lib
    end
  ensure
    rm_r tmpdir
  end

  File.chmod(0755, lib)
  lib
end

def load_extension(name)
  require compile_extension(name)
rescue LoadError
  if %r{/usr/sbin/execerror ruby "\(ld 3 1 main ([/a-zA-Z0-9_\-.]+_spec\.so)"} =~ $!.message
    system('/usr/sbin/execerror', "#{RbConfig::CONFIG["bindir"]}/ruby", "(ld 3 1 main #{$1}")
  end
  raise
end

# Constants
CAPI_SIZEOF_LONG = [0].pack('l!').size