Skip to content

Commit 9d9e9f4

Browse files
committed
Handle including <time.h> in --std=c99 before <ruby.h>
* Add a cexts test for it. * See socketry/io-event#88 for details.
1 parent 410e95a commit 9d9e9f4

File tree

10 files changed

+61
-20
lines changed

10 files changed

+61
-20
lines changed

lib/cext/include/ruby/internal/intern/time.h

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -142,15 +142,7 @@ void rb_tr_time_timeval(VALUE time, struct timeval *result);
142142
* @exception rb_eRangeError `time` is out of range of `timeval::tv_sec`.
143143
* @return A struct that represents the identical time to `num`.
144144
*/
145-
#ifdef TRUFFLERUBY
146-
static inline struct timeval rb_time_timeval(VALUE time) {
147-
struct timeval result;
148-
rb_tr_time_timeval(time, &result);
149-
return result;
150-
}
151-
#else
152145
struct timeval rb_time_timeval(VALUE time);
153-
#endif
154146

155147
#ifdef TRUFFLERUBY
156148
void rb_tr_time_timespec(VALUE time, struct timespec *result);
@@ -163,15 +155,7 @@ void rb_tr_time_timespec(VALUE time, struct timespec *result);
163155
* @exception rb_eRangeError `time` is out of range of `timeval::tv_sec`.
164156
* @return A struct that represents the identical time to `num`.
165157
*/
166-
#ifdef TRUFFLERUBY
167-
static inline struct timespec rb_time_timespec(VALUE time) {
168-
struct timespec result;
169-
rb_tr_time_timespec(time, &result);
170-
return result;
171-
}
172-
#else
173158
struct timespec rb_time_timespec(VALUE time);
174-
#endif
175159

176160
/**
177161
* Identical to rb_time_interval(), except for return type.

lib/cext/include/truffleruby/truffleruby-abi-version.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,6 @@
2020
// $RUBY_VERSION must be the same as TruffleRuby.LANGUAGE_VERSION.
2121
// $ABI_NUMBER starts at 1 and is incremented for every ABI-incompatible change.
2222

23-
#define TRUFFLERUBY_ABI_VERSION "3.2.2.10"
23+
#define TRUFFLERUBY_ABI_VERSION "3.2.2.11"
2424

2525
#endif

src/main/c/cext/time.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,20 @@ void rb_tr_time_timespec(VALUE time_val, struct timespec *result) {
4343
result->tv_nsec = polyglot_as_i64(RUBY_INVOKE_NO_WRAP(time, "tv_nsec"));
4444
}
4545

46+
// Only used with --cexts-sulong
47+
struct timeval rb_time_timeval(VALUE time) {
48+
struct timeval result;
49+
rb_tr_time_timeval(time, &result);
50+
return result;
51+
}
52+
53+
// Only used with --cexts-sulong
54+
struct timespec rb_time_timespec(VALUE time) {
55+
struct timespec result;
56+
rb_tr_time_timespec(time, &result);
57+
return result;
58+
}
59+
4660
VALUE rb_time_timespec_new(const struct timespec *ts, int offset) {
4761
void* is_utc = rb_tr_unwrap(rb_boolean(offset == INT_MAX-1));
4862
void* is_local = rb_tr_unwrap(rb_boolean(offset == INT_MAX));
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/usr/bin/env ruby
2+
3+
require 'no_timespec/no_timespec'
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Hello!
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
require 'mkmf'
2+
$CFLAGS += ' --std=c99'
3+
create_makefile('no_timespec')
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// Include time.h before ruby.h, this has the effect together with --std=c99 to not define struct timespec
2+
#include <time.h>
3+
#include <ruby.h>
4+
5+
void Init_no_timespec() {
6+
// This would fail but what we want to test is that including ruby.h works in this situation
7+
// struct timespec t;
8+
printf("Hello!\n");
9+
}

test/truffle/cexts/no_timespec/lib/no_timespec/.keep

Whitespace-only changes.

tool/generate-cext-trampoline.rb

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@
3232
rb_tr_not_implemented
3333
]
3434

35+
RETURN_STRUCT_BY_VALUE = {
36+
'rb_time_timeval' => 'rb_tr_time_timeval',
37+
'rb_time_timespec' => 'rb_tr_time_timespec',
38+
}
39+
3540
type_regexp = /\b(?:(?:const|unsigned|volatile|struct|enum)\s+)*\w+\b(?:\s+const)?(?:\s*\*+\s*)?/
3641
function_pointer_arg_regexp = /\b\w+\s*\(\*(\w+)\)\s*\([^)]*?\)/
3742
argument_regexp = /\bvoid\b|\.\.\.|#{type_regexp}\s*(\w+)(?:\[\d*\])?|#{function_pointer_arg_regexp}/
@@ -65,7 +70,7 @@ def struct_by_value?(type)
6570
if declaration.include? "\n"
6671
abort "This declaration includes newlines but should not:\n#{declaration}\n\n"
6772
end
68-
if struct_by_value? return_type
73+
if struct_by_value?(return_type) and !RETURN_STRUCT_BY_VALUE.include?(function_name)
6974
abort "Returning a struct by value from Sulong to NFI is not supported for:\n#{declaration}"
7075
end
7176
end
@@ -183,12 +188,15 @@ def struct_by_value?(type)
183188

184189
f.puts "\n// Functions\n\n"
185190
functions.each do |declaration, return_type, function_name, argument_types|
191+
next if RETURN_STRUCT_BY_VALUE.include?(function_name)
186192
f.puts "#undef #{function_name}"
187193
f.puts "static #{declaration.sub(/\{$/, '').rstrip.sub(function_name, "(*impl_#{function_name})")};"
188194
end
189195
f.puts
190196

191197
functions.each do |declaration, return_type, function_name, argument_types|
198+
next if RETURN_STRUCT_BY_VALUE.include?(function_name)
199+
192200
argument_names = argument_types.delete_prefix('(').delete_suffix(')')
193201
argument_names = argument_names.scan(/(?:^|,)\s*(#{argument_regexp})\s*(?=,|$)/o)
194202
argument_names = argument_names.map { |full_arg, name1, name2|
@@ -237,13 +245,32 @@ def struct_by_value?(type)
237245
f.puts
238246
end
239247

248+
f.puts <<C
249+
// Return struct-by-value functions
250+
251+
struct timeval rb_time_timeval(VALUE time) {
252+
struct timeval result;
253+
rb_tr_time_timeval(time, &result);
254+
return result;
255+
}
256+
257+
struct timespec rb_time_timespec(VALUE time) {
258+
struct timespec result;
259+
rb_tr_time_timespec(time, &result);
260+
return result;
261+
}
262+
263+
C
264+
240265
f.puts <<C
241266
// Init functions
267+
242268
void rb_tr_trampoline_init_functions(TruffleEnv* env, void* (*get_libtruffleruby_function)(const char*)) {
243269
nfiContext = (*env)->getTruffleContext(env);
244270
245271
C
246272
functions.each do |declaration, return_type, function_name, argument_types|
273+
next if RETURN_STRUCT_BY_VALUE.include?(function_name)
247274
f.puts " impl_#{function_name} = get_libtruffleruby_function(\"#{function_name}\");"
248275
end
249276
f.puts "}"

tool/jt.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1415,7 +1415,7 @@ def retag(*args)
14151415

14161416
ALL_CEXTS_TESTS = %w[
14171417
tools postinstallhook
1418-
minimum module method globals backtraces xopenssl werror stripped
1418+
minimum module method globals backtraces xopenssl werror no_timespec stripped
14191419
oily_png psd_native
14201420
puma sqlite3 unf_ext json grpc RubyInline msgpack
14211421
]
@@ -1442,7 +1442,7 @@ def retag(*args)
14421442
# Test tools
14431443
run_ruby 'test/truffle/cexts/test_preprocess.rb'
14441444

1445-
when 'minimum', 'module', 'method', 'globals', 'backtraces', 'xopenssl', 'werror', 'stripped'
1445+
when 'minimum', 'module', 'method', 'globals', 'backtraces', 'xopenssl', 'werror', 'no_timespec', 'stripped'
14461446
# Test that we can compile and run some very basic C extensions
14471447
output_file = 'cext-output.txt'
14481448
dir = "test/truffle/cexts/#{test_name}"

0 commit comments

Comments
 (0)