Skip to content

Commit c6628ba

Browse files
committed
[GR-45459] Update to FFI 1.15.5
PullRequest: truffleruby/3761
2 parents d24019b + c70fb0a commit c6628ba

File tree

18 files changed

+151
-55
lines changed

18 files changed

+151
-55
lines changed

doc/contributor/ffi.md

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,18 +27,12 @@ require C extension support for gems using FFI.
2727

2828
## Synchronization
2929

30-
I use a branch `truffleruby-specs-$FFI_RELEASE` on my fork https://github.com/eregon/ffi
31-
which keeps our modifications on top of the FFI release tag we are based on.
32-
`tool/import-ffi.sh` from the latest of these branches should synchronize cleanly.
30+
`tool/import-ffi.sh` from the corresponding FFI version should synchronize cleanly.
3331

34-
In general, changes are done in TruffleRuby first, then I add them to my local `ffi` repository
35-
in the `truffleruby-specs-$FFI_RELEASE` branch with `git cherry-pick`.
36-
This requires `truffleruby` to be added as a remote to the `ffi` repo:
37-
```bash
38-
git remote add truffleruby ../truffleruby-ws/truffleruby
39-
```
32+
In general, changes are done in `ffi` first, and I copy them to truffleruby via `tool/import-ffi.sh` while working on them.
33+
We should upstream all changes we do to `ffi`.
4034

41-
From there we should of course upstream as many changes as possible to minimize the diff.
35+
The only diff we should have is in `src/main/ruby/truffleruby/core/truffle/ffi/pointer_extra.rb` and it should remain small.
4236

4337
## Running Specs in Upstream FFI Repository
4438

lib/truffle/ffi/library.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ module Library
8484
# @raise {RuntimeError} if +mod+ is not a Module
8585
# Test if extended object is a Module. If not, raise RuntimeError.
8686
def self.extended(mod)
87-
raise RuntimeError.new("must only be extended by module") unless mod.kind_of?(Module)
87+
raise RuntimeError.new("must only be extended by module") unless mod.kind_of?(::Module)
8888
end
8989

9090

@@ -126,7 +126,7 @@ def ffi_lib(*names)
126126
else
127127
# TODO better library lookup logic
128128
unless libname.start_with?("/") || FFI::Platform.windows?
129-
path = ['/usr/lib/','/usr/local/lib/','/opt/local/lib/'].find do |pth|
129+
path = ['/usr/lib/','/usr/local/lib/','/opt/local/lib/', '/opt/homebrew/lib/'].find do |pth|
130130
File.exist?(pth + libname)
131131
end
132132
if path

lib/truffle/ffi/platform.rb

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -132,11 +132,8 @@ def self.is_os(os)
132132
end
133133

134134
LIBC = if IS_WINDOWS
135-
if RbConfig::CONFIG['host_os'] =~ /mingw/i
136-
RbConfig::CONFIG['RUBY_SO_NAME'].split('-')[-2] + '.dll'
137-
else
138-
"ucrtbase.dll"
139-
end
135+
crtname = RbConfig::CONFIG["RUBY_SO_NAME"][/msvc\w+/] || 'ucrtbase'
136+
"#{crtname}.dll"
140137
elsif IS_GNU
141138
GNU_LIBC
142139
elsif OS == 'cygwin'

lib/truffle/ffi/tools/const_generator.rb

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -105,9 +105,10 @@ def const(name, format = nil, cast = '', ruby_name = nil, converter = nil,
105105
# @return [nil]
106106
# @raise if a constant is missing and +:required+ was set to +true+ (see {#initialize})
107107
def calculate(options = {})
108-
binary = File.join Dir.tmpdir, "rb_const_gen_bin_#{Process.pid}"
108+
binary_path = nil
109109

110110
Tempfile.open("#{@prefix}.const_generator") do |f|
111+
binary_path = f.path + ".bin"
111112
@includes.each do |inc|
112113
f.puts "#include <#{inc}>"
113114
end
@@ -124,16 +125,17 @@ def calculate(options = {})
124125
f.puts "\n\treturn 0;\n}"
125126
f.flush
126127

127-
output = `gcc #{options[:cppflags]} -D_DARWIN_USE_64_BIT_INODE -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -x c -Wall -Werror #{f.path} -o #{binary} 2>&1`
128+
cc = ENV['CC'] || 'gcc'
129+
output = `#{cc} #{options[:cppflags]} -D_DARWIN_USE_64_BIT_INODE -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -x c -Wall -Werror #{f.path} -o #{binary_path} 2>&1`
128130

129131
unless $?.success? then
130132
output = output.split("\n").map { |l| "\t#{l}" }.join "\n"
131133
raise "Compilation error generating constants #{@prefix}:\n#{output}"
132134
end
133135
end
134136

135-
output = `#{binary}`
136-
File.unlink(binary + (FFI::Platform.windows? ? ".exe" : ""))
137+
output = `#{binary_path}`
138+
File.unlink(binary_path + (FFI::Platform.windows? ? ".exe" : ""))
137139
output.each_line do |line|
138140
line =~ /^(\S+)\s(.*)$/
139141
const = @constants[$1]

lib/truffle/ffi/tools/struct_generator.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,8 @@ def calculate(options = {})
8282
f.puts "\n return 0;\n}"
8383
f.flush
8484

85-
output = `gcc #{options[:cppflags]} #{options[:cflags]} -D_DARWIN_USE_64_BIT_INODE -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -x c -Wall -Werror #{f.path} -o #{binary} 2>&1`
85+
cc = ENV['CC'] || 'gcc'
86+
output = `#{cc} #{options[:cppflags]} #{options[:cflags]} -D_DARWIN_USE_64_BIT_INODE -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -x c -Wall -Werror #{f.path} -o #{binary} 2>&1`
8687

8788
unless $?.success? then
8889
@found = false

lib/truffle/ffi/variadic.rb

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,15 +32,6 @@
3232

3333
module FFI
3434
class VariadicInvoker
35-
def init(arg_types, type_map)
36-
@fixed = Array.new
37-
@type_map = type_map
38-
arg_types.each_with_index do |type, i|
39-
@fixed << type unless type == Type::VARARGS
40-
end
41-
end
42-
43-
4435
def call(*args, &block)
4536
param_types = Array.new(@fixed)
4637
param_values = Array.new

lib/truffle/ffi/version.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
module FFI
2-
VERSION = '1.14.2'
2+
VERSION = '1.15.5'
33
end

spec/ffi/Gemfile.lock

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,3 @@ PLATFORMS
2121

2222
DEPENDENCIES
2323
rspec (~> 3.0)
24-
25-
BUNDLED WITH
26-
2.1.4

spec/ffi/async_callback_spec.rb

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,19 +19,35 @@ module LibTest
1919
skip "not yet supported on TruffleRuby" if RUBY_ENGINE == "truffleruby"
2020
v = 0xdeadbeef
2121
called = false
22-
cb = Proc.new {|i| v = i; called = true }
22+
cb = Proc.new {|i| v = i; called = Thread.current }
2323
LibTest.testAsyncCallback(cb, 0x7fffffff)
24-
expect(called).to be true
24+
expect(called).to be_kind_of(Thread)
25+
expect(called).to_not eq(Thread.current)
2526
expect(v).to eq(0x7fffffff)
2627
end
2728

2829
it "called a second time" do
2930
skip "not yet supported on TruffleRuby" if RUBY_ENGINE == "truffleruby"
30-
v = 0xdeadbeef
31-
called = false
32-
cb = Proc.new {|i| v = i; called = true }
33-
LibTest.testAsyncCallback(cb, 0x7fffffff)
34-
expect(called).to be true
35-
expect(v).to eq(0x7fffffff)
31+
v = 1
32+
th1 = th2 = false
33+
LibTest.testAsyncCallback(2) { |i| v += i; th1 = Thread.current }
34+
LibTest.testAsyncCallback(3) { |i| v += i; th2 = Thread.current }
35+
expect(th1).to be_kind_of(Thread)
36+
expect(th2).to be_kind_of(Thread)
37+
expect(th1).to_not eq(Thread.current)
38+
expect(th2).to_not eq(Thread.current)
39+
expect(th1).to_not eq(th2)
40+
expect(v).to eq(6)
41+
end
42+
43+
it "sets the name of the thread that runs the callback" do
44+
skip "not yet supported on TruffleRuby" if RUBY_ENGINE == "truffleruby"
45+
skip "not yet supported on JRuby" if RUBY_ENGINE == "jruby"
46+
47+
callback_runner_thread = nil
48+
49+
LibTest.testAsyncCallback(proc { callback_runner_thread = Thread.current }, 0)
50+
51+
expect(callback_runner_thread.name).to eq("FFI Callback Runner")
3652
end
3753
end

spec/ffi/callback_spec.rb

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ class S8F32S32 < FFI::Struct
4949
callback :cbVrU32, [ ], :uint
5050
callback :cbVrL, [ ], :long
5151
callback :cbVrUL, [ ], :ulong
52+
callback :cbVrF, [ ], :float
53+
callback :cbVrD, [ ], :double
5254
callback :cbVrS64, [ ], :long_long
5355
callback :cbVrU64, [ ], :ulong_long
5456
callback :cbVrP, [], :pointer
@@ -70,6 +72,8 @@ class S8F32S32 < FFI::Struct
7072
attach_function :testCallbackVrU16, :testClosureVrS, [ :cbVrU16 ], :ushort
7173
attach_function :testCallbackVrS32, :testClosureVrI, [ :cbVrS32 ], :int
7274
attach_function :testCallbackVrU32, :testClosureVrI, [ :cbVrU32 ], :uint
75+
attach_function :testCallbackVrF, :testClosureVrF, [ :cbVrF ], :float
76+
attach_function :testCallbackVrD, :testClosureVrD, [ :cbVrD ], :double
7377
attach_function :testCallbackVrL, :testClosureVrL, [ :cbVrL ], :long
7478
attach_function :testCallbackVrZ, :testClosureVrZ, [ :cbVrZ ], :bool
7579
attach_function :testCallbackVrUL, :testClosureVrL, [ :cbVrUL ], :ulong
@@ -86,7 +90,6 @@ class S8F32S32 < FFI::Struct
8690
attach_variable :pVrS8, :gvar_pointer, :pointer
8791
attach_function :testGVarCallbackVrS8, :testClosureVrB, [ :pointer ], :char
8892
attach_function :testOptionalCallbackCrV, :testOptionalClosureBrV, [ :cbCrV, :char ], :void
89-
9093
end
9194

9295
it "returning :char (0)" do
@@ -261,6 +264,14 @@ class S8F32S32 < FFI::Struct
261264
expect(LibTest.testCallbackVrZ { true }).to be true
262265
end
263266

267+
it "returning float" do
268+
expect(LibTest.testCallbackVrF { 1.234567890123456789 }).to be_within(1E-7).of(1.234567890123456789)
269+
end
270+
271+
it "returning double" do
272+
expect(LibTest.testCallbackVrD { 1.234567890123456789 }).to be_within(1E-15).of(1.234567890123456789)
273+
end
274+
264275
it "returning :pointer (nil)" do
265276
expect(LibTest.testCallbackVrP { nil }).to be_null
266277
end

0 commit comments

Comments
 (0)