itsi 0.2.21 → 0.2.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Cargo.lock +24 -10
- data/Cargo.toml +4 -0
- data/Rakefile +4 -0
- data/crates/itsi_scheduler/Cargo.toml +1 -1
- data/crates/itsi_server/Cargo.toml +1 -1
- data/crates/itsi_server/src/server/signal.rs +7 -5
- data/gems/scheduler/Cargo.lock +516 -3984
- data/gems/scheduler/Cargo.toml +4 -0
- data/gems/scheduler/Gemfile +11 -0
- data/gems/scheduler/Rakefile +21 -6
- data/gems/scheduler/itsi-scheduler.gemspec +5 -1
- data/gems/scheduler/lib/itsi/scheduler/native_extension.rb +34 -0
- data/gems/scheduler/lib/itsi/scheduler/version.rb +1 -1
- data/gems/scheduler/lib/itsi/scheduler.rb +1 -1
- data/gems/scheduler/test/test_block_unblock.rb +1 -1
- data/gems/scheduler/vendor/rb-sys-build/.cargo-ok +1 -0
- data/gems/scheduler/vendor/rb-sys-build/.cargo_vcs_info.json +6 -0
- data/gems/scheduler/vendor/rb-sys-build/Cargo.lock +294 -0
- data/gems/scheduler/vendor/rb-sys-build/Cargo.toml +71 -0
- data/gems/scheduler/vendor/rb-sys-build/Cargo.toml.orig +32 -0
- data/gems/scheduler/vendor/rb-sys-build/LICENSE-APACHE +190 -0
- data/gems/scheduler/vendor/rb-sys-build/LICENSE-MIT +21 -0
- data/gems/scheduler/vendor/rb-sys-build/src/bindings/sanitizer.rs +185 -0
- data/gems/scheduler/vendor/rb-sys-build/src/bindings/stable_api.rs +247 -0
- data/gems/scheduler/vendor/rb-sys-build/src/bindings/wrapper.h +71 -0
- data/gems/scheduler/vendor/rb-sys-build/src/bindings.rs +280 -0
- data/gems/scheduler/vendor/rb-sys-build/src/cc.rs +421 -0
- data/gems/scheduler/vendor/rb-sys-build/src/lib.rs +12 -0
- data/gems/scheduler/vendor/rb-sys-build/src/rb_config/flags.rs +101 -0
- data/gems/scheduler/vendor/rb-sys-build/src/rb_config/library.rs +132 -0
- data/gems/scheduler/vendor/rb-sys-build/src/rb_config/search_path.rs +57 -0
- data/gems/scheduler/vendor/rb-sys-build/src/rb_config.rs +906 -0
- data/gems/scheduler/vendor/rb-sys-build/src/utils.rs +53 -0
- data/gems/server/Cargo.lock +24 -37
- data/gems/server/Cargo.toml +4 -0
- data/gems/server/Gemfile +23 -0
- data/gems/server/Rakefile +39 -7
- data/gems/server/itsi-server.gemspec +5 -1
- data/gems/server/lib/itsi/server/native_extension.rb +34 -0
- data/gems/server/lib/itsi/server/version.rb +1 -1
- data/gems/server/lib/itsi/server.rb +10 -2
- data/gems/server/test/rack/test_rack_server.rb +14 -2
- data/gems/server/vendor/rb-sys-build/.cargo-ok +1 -0
- data/gems/server/vendor/rb-sys-build/.cargo_vcs_info.json +6 -0
- data/gems/server/vendor/rb-sys-build/Cargo.lock +294 -0
- data/gems/server/vendor/rb-sys-build/Cargo.toml +71 -0
- data/gems/server/vendor/rb-sys-build/Cargo.toml.orig +32 -0
- data/gems/server/vendor/rb-sys-build/LICENSE-APACHE +190 -0
- data/gems/server/vendor/rb-sys-build/LICENSE-MIT +21 -0
- data/gems/server/vendor/rb-sys-build/src/bindings/sanitizer.rs +185 -0
- data/gems/server/vendor/rb-sys-build/src/bindings/stable_api.rs +247 -0
- data/gems/server/vendor/rb-sys-build/src/bindings/wrapper.h +71 -0
- data/gems/server/vendor/rb-sys-build/src/bindings.rs +280 -0
- data/gems/server/vendor/rb-sys-build/src/cc.rs +421 -0
- data/gems/server/vendor/rb-sys-build/src/lib.rs +12 -0
- data/gems/server/vendor/rb-sys-build/src/rb_config/flags.rs +101 -0
- data/gems/server/vendor/rb-sys-build/src/rb_config/library.rs +132 -0
- data/gems/server/vendor/rb-sys-build/src/rb_config/search_path.rs +57 -0
- data/gems/server/vendor/rb-sys-build/src/rb_config.rs +906 -0
- data/gems/server/vendor/rb-sys-build/src/utils.rs +53 -0
- data/lib/itsi/version.rb +1 -1
- data/script/ci/resolve_version.rb +32 -0
- data/script/ci/set_version.rb +53 -0
- data/script/ci/setup_cibuildgem_rake_compiler.sh +63 -0
- data/script/ci/smoke_scheduler.rb +24 -0
- data/script/ci/smoke_server.rb +38 -0
- data/vendor/rb-sys-build/.cargo-ok +1 -0
- data/vendor/rb-sys-build/.cargo_vcs_info.json +6 -0
- data/vendor/rb-sys-build/Cargo.lock +294 -0
- data/vendor/rb-sys-build/Cargo.toml +71 -0
- data/vendor/rb-sys-build/Cargo.toml.orig +32 -0
- data/vendor/rb-sys-build/LICENSE-APACHE +190 -0
- data/vendor/rb-sys-build/LICENSE-MIT +21 -0
- data/vendor/rb-sys-build/src/bindings/sanitizer.rs +185 -0
- data/vendor/rb-sys-build/src/bindings/stable_api.rs +247 -0
- data/vendor/rb-sys-build/src/bindings/wrapper.h +71 -0
- data/vendor/rb-sys-build/src/bindings.rs +280 -0
- data/vendor/rb-sys-build/src/cc.rs +421 -0
- data/vendor/rb-sys-build/src/lib.rs +12 -0
- data/vendor/rb-sys-build/src/rb_config/flags.rs +101 -0
- data/vendor/rb-sys-build/src/rb_config/library.rs +132 -0
- data/vendor/rb-sys-build/src/rb_config/search_path.rs +57 -0
- data/vendor/rb-sys-build/src/rb_config.rs +906 -0
- data/vendor/rb-sys-build/src/utils.rs +53 -0
- metadata +68 -5
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
use std::vec;
|
|
2
|
+
|
|
3
|
+
use quote::ToTokens;
|
|
4
|
+
|
|
5
|
+
use crate::RbConfig;
|
|
6
|
+
|
|
7
|
+
const OPAQUE_STRUCTS: [&str; 4] = ["RString", "RArray", "RData", "RTypedData"];
|
|
8
|
+
|
|
9
|
+
const OPAQUE_STRUCTS_RUBY_3_3: [&str; 3] = [
|
|
10
|
+
"rb_matchext_struct",
|
|
11
|
+
"rb_internal_thread_event_data",
|
|
12
|
+
"rb_io_internal_buffer",
|
|
13
|
+
];
|
|
14
|
+
|
|
15
|
+
/// Generate opaque structs for the given bindings.
|
|
16
|
+
pub fn opaqueify_bindings(
|
|
17
|
+
rbconfig: &RbConfig,
|
|
18
|
+
bindings: bindgen::Builder,
|
|
19
|
+
wrapper_h: &mut String,
|
|
20
|
+
) -> bindgen::Builder {
|
|
21
|
+
let version_specific_opaque_structs =
|
|
22
|
+
get_version_specific_opaque_structs(rbconfig.major_minor());
|
|
23
|
+
let structs_to_opaque = OPAQUE_STRUCTS
|
|
24
|
+
.iter()
|
|
25
|
+
.chain(&version_specific_opaque_structs);
|
|
26
|
+
|
|
27
|
+
structs_to_opaque.fold(bindings, |bindings, name| {
|
|
28
|
+
gen_opaque_struct(bindings, name, wrapper_h)
|
|
29
|
+
})
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/// Categorize all bindings into stable, unstable, and internal.
|
|
33
|
+
pub fn categorize_bindings(syntax: &mut syn::File) {
|
|
34
|
+
let mut normal_items = Vec::new();
|
|
35
|
+
let mut unstable_items = Vec::new();
|
|
36
|
+
let mut internal_items = Vec::new();
|
|
37
|
+
let mut excluded_items = Vec::new();
|
|
38
|
+
let mut opaque_items = Vec::new();
|
|
39
|
+
let mut opaque_idents_to_swap = Vec::new();
|
|
40
|
+
|
|
41
|
+
for item in syntax.items.iter_mut() {
|
|
42
|
+
if let syn::Item::Struct(s) = item {
|
|
43
|
+
if s.ident.to_string().contains("rb_sys__Opaque__") {
|
|
44
|
+
let new_name = s.ident.to_string().replace("rb_sys__Opaque__", "");
|
|
45
|
+
s.ident = syn::Ident::new(&new_name, s.ident.span());
|
|
46
|
+
opaque_idents_to_swap.push(new_name);
|
|
47
|
+
|
|
48
|
+
opaque_items.push(item.clone());
|
|
49
|
+
} else {
|
|
50
|
+
normal_items.push(item.clone());
|
|
51
|
+
}
|
|
52
|
+
} else if let syn::Item::Type(t) = item {
|
|
53
|
+
if t.ident.to_string().contains("rb_sys__Opaque__") {
|
|
54
|
+
let new_name = t.ident.to_string().replace("rb_sys__Opaque__", "");
|
|
55
|
+
t.ident = syn::Ident::new(&new_name, t.ident.span());
|
|
56
|
+
opaque_idents_to_swap.push(new_name);
|
|
57
|
+
|
|
58
|
+
opaque_items.push(item.clone());
|
|
59
|
+
} else {
|
|
60
|
+
normal_items.push(item.clone());
|
|
61
|
+
}
|
|
62
|
+
} else {
|
|
63
|
+
if let syn::Item::Fn(ref mut f) = item {
|
|
64
|
+
if f.sig.ident.to_string().contains("bindgen_test_") {
|
|
65
|
+
let body = &mut f.block;
|
|
66
|
+
let code = body.clone().to_token_stream().to_string();
|
|
67
|
+
let new_code = code.replace("rb_sys__Opaque__", "super::stable::");
|
|
68
|
+
let new_code = syn::parse_str::<syn::Block>(&new_code).unwrap();
|
|
69
|
+
|
|
70
|
+
*body = syn::parse_quote! {
|
|
71
|
+
{
|
|
72
|
+
#[allow(unused)]
|
|
73
|
+
use super::internal::*;
|
|
74
|
+
#new_code;
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
normal_items.push(item.clone());
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
for item in normal_items.iter_mut() {
|
|
85
|
+
if let syn::Item::Type(ref mut t) = item {
|
|
86
|
+
if let Ok(syn::Type::Path(ref mut type_path)) =
|
|
87
|
+
syn::parse2::<syn::Type>(t.ty.to_token_stream())
|
|
88
|
+
{
|
|
89
|
+
if opaque_idents_to_swap.contains(&type_path.path.segments[0].ident.to_string()) {
|
|
90
|
+
let new_ident = syn::Ident::new(
|
|
91
|
+
&type_path.path.segments[0].ident.to_string(),
|
|
92
|
+
type_path.path.segments[0].ident.span(),
|
|
93
|
+
);
|
|
94
|
+
t.ty = syn::parse_quote! { crate::internal::#new_ident };
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
for mut item in normal_items {
|
|
101
|
+
if let syn::Item::Struct(s) = &mut item {
|
|
102
|
+
if opaque_idents_to_swap.contains(&s.ident.to_string()) {
|
|
103
|
+
internal_items.push(syn::Item::Struct(s.clone()));
|
|
104
|
+
s.attrs.push(syn::parse_quote! {
|
|
105
|
+
#[deprecated(note = "To improve API stability with ruby-head, direct usage of Ruby internal structs has been deprecated. To migrate, please replace the usage of this internal struct with its counterpart in the `rb_sys::stable` module. For example, instead of `use rb_sys::rb_sys__Opaque__ExampleStruct;`, use `use rb_sys::stable::ExampleStruct;`. If you need to access the internals of these items, you can use the provided `rb-sys::macros` instead.")]
|
|
106
|
+
});
|
|
107
|
+
unstable_items.push(item);
|
|
108
|
+
} else {
|
|
109
|
+
excluded_items.push(item);
|
|
110
|
+
}
|
|
111
|
+
} else if let syn::Item::Type(t) = &mut item {
|
|
112
|
+
if opaque_idents_to_swap.contains(&t.ident.to_string()) {
|
|
113
|
+
internal_items.push(syn::Item::Type(t.clone()));
|
|
114
|
+
t.attrs.push(syn::parse_quote! {
|
|
115
|
+
#[deprecated(note = "To improve API stability with ruby-head, direct usage of Ruby internal structs has been deprecated. To migrate, please replace the usage of this internal struct with its counterpart in the `rb_sys::stable` module. For example, instead of `use rb_sys::rb_sys__Opaque__ExampleStruct;`, use `use rb_sys::stable::ExampleStruct;`. If you need to access the internals of these items, you can use the provided `rb-sys::macros` instead.")]
|
|
116
|
+
});
|
|
117
|
+
unstable_items.push(item);
|
|
118
|
+
} else {
|
|
119
|
+
excluded_items.push(item);
|
|
120
|
+
}
|
|
121
|
+
} else {
|
|
122
|
+
excluded_items.push(item);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Perform a pass on all std::fmt::Debug implementations to fully qualify opaque structs
|
|
127
|
+
for item in excluded_items.iter_mut() {
|
|
128
|
+
if let syn::Item::Impl(ref mut impl_item) = item {
|
|
129
|
+
if let Some((_, syn::Path { segments, .. }, _)) = impl_item.trait_.as_ref() {
|
|
130
|
+
if segments.iter().any(|segment| segment.ident == "Debug") {
|
|
131
|
+
if let syn::Type::Path(ref mut path) = *impl_item.self_ty {
|
|
132
|
+
if opaque_idents_to_swap.contains(&path.to_token_stream().to_string()) {
|
|
133
|
+
*impl_item.self_ty = syn::parse_quote! { crate::internal::#path };
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
*syntax = syn::parse_quote! {
|
|
142
|
+
/// Contains all items that are not yet categorized by ABI stability.
|
|
143
|
+
/// These items are candidates for promotion to `stable` or `unstable`
|
|
144
|
+
/// in the future.
|
|
145
|
+
pub mod uncategorized {
|
|
146
|
+
#(#excluded_items)*
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/// Contains all items that are considered unstable ABI and should be
|
|
150
|
+
/// avoided. Any items in this list offer a stable alternative for most
|
|
151
|
+
/// use cases.
|
|
152
|
+
pub mod unstable {
|
|
153
|
+
use super::uncategorized::*;
|
|
154
|
+
|
|
155
|
+
#(#unstable_items)*
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/// Contains all items that are considered stable ABI and are safe to
|
|
159
|
+
/// use. These items are intentionally opaque to prevent accidental
|
|
160
|
+
/// compatibility issues.
|
|
161
|
+
///
|
|
162
|
+
/// If you need to access the internals of these items, please open an
|
|
163
|
+
/// issue.
|
|
164
|
+
pub mod stable {
|
|
165
|
+
#(#opaque_items)*
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/// Unstable items for usage internally in rb_sys to avoid deprecated warnings.
|
|
169
|
+
#[allow(dead_code)]
|
|
170
|
+
pub (crate) mod internal {
|
|
171
|
+
use super::uncategorized::*;
|
|
172
|
+
|
|
173
|
+
#(#internal_items)*
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
fn gen_opaque_struct(
|
|
179
|
+
bindings: bindgen::Builder,
|
|
180
|
+
name: &str,
|
|
181
|
+
wrapper_h: &mut String,
|
|
182
|
+
) -> bindgen::Builder {
|
|
183
|
+
let struct_name = format!("rb_sys__Opaque__{}", name);
|
|
184
|
+
wrapper_h.push_str(&format!(
|
|
185
|
+
"struct {} {{ struct {} dummy; }};\n",
|
|
186
|
+
struct_name, name
|
|
187
|
+
));
|
|
188
|
+
|
|
189
|
+
bindings
|
|
190
|
+
.opaque_type(&struct_name)
|
|
191
|
+
.allowlist_type(struct_name)
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
fn get_version_specific_opaque_structs(major_minor: Option<(u32, u32)>) -> Vec<&'static str> {
|
|
195
|
+
let Some(major_minor) = major_minor else {
|
|
196
|
+
return vec![];
|
|
197
|
+
};
|
|
198
|
+
let mut result = vec![];
|
|
199
|
+
let (major, minor) = major_minor;
|
|
200
|
+
|
|
201
|
+
if major > 3 || (major == 3 && minor >= 3) {
|
|
202
|
+
result.extend(OPAQUE_STRUCTS_RUBY_3_3)
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
result
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
#[cfg(test)]
|
|
209
|
+
mod tests {
|
|
210
|
+
use super::*;
|
|
211
|
+
|
|
212
|
+
#[test]
|
|
213
|
+
fn test_get_version_specific_opaque_structs() {
|
|
214
|
+
// No version info
|
|
215
|
+
assert!(get_version_specific_opaque_structs(None).is_empty());
|
|
216
|
+
|
|
217
|
+
// Ruby 3.2.x - too old for 3.3 structs
|
|
218
|
+
assert!(get_version_specific_opaque_structs(Some((3, 2))).is_empty());
|
|
219
|
+
|
|
220
|
+
// Ruby 3.3.x - should include 3.3 structs
|
|
221
|
+
assert_eq!(
|
|
222
|
+
get_version_specific_opaque_structs(Some((3, 3))),
|
|
223
|
+
OPAQUE_STRUCTS_RUBY_3_3.to_vec()
|
|
224
|
+
);
|
|
225
|
+
|
|
226
|
+
// Ruby 3.4.x - should include 3.3 structs
|
|
227
|
+
assert_eq!(
|
|
228
|
+
get_version_specific_opaque_structs(Some((3, 4))),
|
|
229
|
+
OPAQUE_STRUCTS_RUBY_3_3.to_vec()
|
|
230
|
+
);
|
|
231
|
+
|
|
232
|
+
// Ruby 4.0.x - should include 3.3 structs (this was the bug!)
|
|
233
|
+
assert_eq!(
|
|
234
|
+
get_version_specific_opaque_structs(Some((4, 0))),
|
|
235
|
+
OPAQUE_STRUCTS_RUBY_3_3.to_vec()
|
|
236
|
+
);
|
|
237
|
+
|
|
238
|
+
// Ruby 4.1.x - should include 3.3 structs
|
|
239
|
+
assert_eq!(
|
|
240
|
+
get_version_specific_opaque_structs(Some((4, 1))),
|
|
241
|
+
OPAQUE_STRUCTS_RUBY_3_3.to_vec()
|
|
242
|
+
);
|
|
243
|
+
|
|
244
|
+
// Ruby 2.7.x - too old
|
|
245
|
+
assert!(get_version_specific_opaque_structs(Some((2, 7))).is_empty());
|
|
246
|
+
}
|
|
247
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
#include "ruby.h"
|
|
2
|
+
|
|
3
|
+
#ifdef HAVE_RUBY_DEBUG_H
|
|
4
|
+
#include "ruby/debug.h"
|
|
5
|
+
#endif
|
|
6
|
+
#ifdef HAVE_RUBY_DEFINES_H
|
|
7
|
+
#include "ruby/defines.h"
|
|
8
|
+
#endif
|
|
9
|
+
#ifdef HAVE_RUBY_ENCODING_H
|
|
10
|
+
#include "ruby/encoding.h"
|
|
11
|
+
#endif
|
|
12
|
+
#ifdef HAVE_RUBY_FIBER_SCHEDULER_H
|
|
13
|
+
#include "ruby/fiber/scheduler.h"
|
|
14
|
+
#endif
|
|
15
|
+
#ifdef HAVE_RUBY_INTERN_H
|
|
16
|
+
#include "ruby/intern.h"
|
|
17
|
+
#endif
|
|
18
|
+
#ifdef HAVE_RUBY_IO_H
|
|
19
|
+
#include "ruby/io.h"
|
|
20
|
+
#endif
|
|
21
|
+
#ifdef HAVE_RUBY_MEMORY_VIEW_H
|
|
22
|
+
#include "ruby/memory_view.h"
|
|
23
|
+
#endif
|
|
24
|
+
#ifdef HAVE_RUBY_MISSING_H
|
|
25
|
+
#include "ruby/missing.h"
|
|
26
|
+
#endif
|
|
27
|
+
#ifdef HAVE_RUBY_ONIGMO_H
|
|
28
|
+
#include "ruby/onigmo.h"
|
|
29
|
+
#endif
|
|
30
|
+
#ifdef HAVE_RUBY_ONIGURUMA_H
|
|
31
|
+
#include "ruby/oniguruma.h"
|
|
32
|
+
#endif
|
|
33
|
+
#ifdef HAVE_RUBY_RACTOR_H
|
|
34
|
+
#include "ruby/ractor.h"
|
|
35
|
+
#endif
|
|
36
|
+
#ifdef HAVE_RUBY_RANDOM_H
|
|
37
|
+
#include "ruby/random.h"
|
|
38
|
+
#endif
|
|
39
|
+
#ifdef HAVE_RUBY_RE_H
|
|
40
|
+
#include "ruby/re.h"
|
|
41
|
+
#endif
|
|
42
|
+
#ifdef HAVE_RUBY_REGEX_H
|
|
43
|
+
#include "ruby/regex.h"
|
|
44
|
+
#endif
|
|
45
|
+
#ifdef HAVE_RUBY_RUBY_H
|
|
46
|
+
#include "ruby/ruby.h"
|
|
47
|
+
#endif
|
|
48
|
+
#ifdef HAVE_RUBY_ST_H
|
|
49
|
+
#include "ruby/st.h"
|
|
50
|
+
#endif
|
|
51
|
+
#ifdef HAVE_RUBY_THREAD_H
|
|
52
|
+
#include "ruby/thread.h"
|
|
53
|
+
#endif
|
|
54
|
+
#ifdef HAVE_RUBY_THREAD_NATIVE_H
|
|
55
|
+
#include "ruby/thread_native.h"
|
|
56
|
+
#endif
|
|
57
|
+
#ifdef HAVE_RUBY_UTIL_H
|
|
58
|
+
#include "ruby/util.h"
|
|
59
|
+
#endif
|
|
60
|
+
#ifdef HAVE_RUBY_VERSION_H
|
|
61
|
+
#include "ruby/version.h"
|
|
62
|
+
#endif
|
|
63
|
+
#ifdef HAVE_RUBY_VM_H
|
|
64
|
+
#include "ruby/vm.h"
|
|
65
|
+
#endif
|
|
66
|
+
#ifdef HAVE_RUBY_WIN32_H
|
|
67
|
+
#include "ruby/win32.h"
|
|
68
|
+
#endif
|
|
69
|
+
#ifdef HAVE_RUBY_IO_BUFFER_H
|
|
70
|
+
#include "ruby/io/buffer.h"
|
|
71
|
+
#endif
|
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
mod sanitizer;
|
|
2
|
+
mod stable_api;
|
|
3
|
+
|
|
4
|
+
use crate::cc::Build;
|
|
5
|
+
use crate::utils::is_msvc;
|
|
6
|
+
use crate::{debug_log, RbConfig};
|
|
7
|
+
use quote::ToTokens;
|
|
8
|
+
use stable_api::{categorize_bindings, opaqueify_bindings};
|
|
9
|
+
use std::fs::File;
|
|
10
|
+
use std::io::Write;
|
|
11
|
+
use std::path::{Path, PathBuf};
|
|
12
|
+
use std::{env, error::Error};
|
|
13
|
+
use syn::{Expr, ExprLit, ItemConst, Lit};
|
|
14
|
+
|
|
15
|
+
const WRAPPER_H_CONTENT: &str = include_str!("bindings/wrapper.h");
|
|
16
|
+
|
|
17
|
+
/// Generate bindings for the Ruby using bindgen.
|
|
18
|
+
pub fn generate(
|
|
19
|
+
rbconfig: &RbConfig,
|
|
20
|
+
static_ruby: bool,
|
|
21
|
+
cfg_out: &mut File,
|
|
22
|
+
) -> Result<PathBuf, Box<dyn Error>> {
|
|
23
|
+
let out_dir = PathBuf::from(env::var("OUT_DIR")?);
|
|
24
|
+
|
|
25
|
+
let mut clang_args = vec![];
|
|
26
|
+
if let Some(ruby_include_dir) = rbconfig.get("rubyhdrdir") {
|
|
27
|
+
clang_args.push(format!("-I{}", ruby_include_dir));
|
|
28
|
+
}
|
|
29
|
+
if let Some(ruby_arch_include_dir) = rbconfig.get("rubyarchhdrdir") {
|
|
30
|
+
clang_args.push(format!("-I{}", ruby_arch_include_dir));
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
clang_args.extend(Build::default_cflags());
|
|
34
|
+
clang_args.extend(rbconfig.cflags.clone());
|
|
35
|
+
clang_args.extend(rbconfig.cppflags());
|
|
36
|
+
|
|
37
|
+
// On Windows x86_64, we need to handle AVX512 FP16 compatibility issues
|
|
38
|
+
// Clang 20+ includes types like __m512h that aren't compatible with bindgen
|
|
39
|
+
if cfg!(target_os = "windows") && cfg!(target_arch = "x86_64") {
|
|
40
|
+
// For MinGW toolchain, disable SSE/AVX only for bindgen
|
|
41
|
+
// This prevents intrinsics headers from loading but doesn't affect the final binary
|
|
42
|
+
if !is_msvc() {
|
|
43
|
+
clang_args.push("-mno-sse".to_string());
|
|
44
|
+
clang_args.push("-mno-avx".to_string());
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
debug_log!("INFO: using bindgen with clang args: {:?}", clang_args);
|
|
49
|
+
|
|
50
|
+
let mut wrapper_h = WRAPPER_H_CONTENT.to_string();
|
|
51
|
+
|
|
52
|
+
if !is_msvc() {
|
|
53
|
+
wrapper_h.push_str("#ifdef HAVE_RUBY_ATOMIC_H\n");
|
|
54
|
+
wrapper_h.push_str("#include \"ruby/atomic.h\"\n");
|
|
55
|
+
wrapper_h.push_str("#endif\n");
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if rbconfig.have_ruby_header("ruby/io/buffer.h") {
|
|
59
|
+
clang_args.push("-DHAVE_RUBY_IO_BUFFER_H".to_string());
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
let bindings = default_bindgen(clang_args, rbconfig)
|
|
63
|
+
.allowlist_file(".*ruby.*")
|
|
64
|
+
.blocklist_item("ruby_abi_version")
|
|
65
|
+
.blocklist_function("rb_tr_abi_version")
|
|
66
|
+
.blocklist_function("^__.*")
|
|
67
|
+
.blocklist_item("RData")
|
|
68
|
+
.blocklist_function("rb_tr_rdata")
|
|
69
|
+
.blocklist_function("rb_tr_rtypeddata")
|
|
70
|
+
.parse_callbacks(Box::new(bindgen::CargoCallbacks::new()));
|
|
71
|
+
|
|
72
|
+
let bindings = if cfg!(feature = "bindgen-rbimpls") {
|
|
73
|
+
bindings
|
|
74
|
+
} else {
|
|
75
|
+
bindings
|
|
76
|
+
.blocklist_item("^rbimpl_.*")
|
|
77
|
+
.blocklist_item("^RBIMPL_.*")
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
let bindings = if cfg!(feature = "bindgen-deprecated-types") {
|
|
81
|
+
bindings
|
|
82
|
+
} else {
|
|
83
|
+
bindings.blocklist_item("^_bindgen_ty_9.*")
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
let bindings = opaqueify_bindings(rbconfig, bindings, &mut wrapper_h);
|
|
87
|
+
|
|
88
|
+
let mut tokens = {
|
|
89
|
+
write!(std::io::stderr(), "{}", wrapper_h)?;
|
|
90
|
+
let bindings = bindings.header_contents("wrapper.h", &wrapper_h);
|
|
91
|
+
let code_string = bindings.generate()?.to_string();
|
|
92
|
+
syn::parse_file(&code_string)?
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
let slug = rbconfig.ruby_version_slug();
|
|
96
|
+
let crate_version = env!("CARGO_PKG_VERSION");
|
|
97
|
+
let out_path = out_dir.join(format!("bindings-{}-{}.rs", crate_version, slug));
|
|
98
|
+
|
|
99
|
+
let code = {
|
|
100
|
+
sanitizer::ensure_backwards_compatible_encoding_pointers(&mut tokens);
|
|
101
|
+
clean_docs(rbconfig, &mut tokens);
|
|
102
|
+
|
|
103
|
+
if is_msvc() {
|
|
104
|
+
qualify_symbols_for_msvc(&mut tokens, static_ruby, rbconfig);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
push_cargo_cfg_from_bindings(&tokens, cfg_out)?;
|
|
108
|
+
categorize_bindings(&mut tokens);
|
|
109
|
+
tokens.into_token_stream().to_string()
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
let mut out_file = File::create(&out_path)?;
|
|
113
|
+
std::io::Write::write_all(&mut out_file, code.as_bytes())?;
|
|
114
|
+
run_rustfmt(&out_path);
|
|
115
|
+
|
|
116
|
+
Ok(out_path)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
fn run_rustfmt(path: &Path) {
|
|
120
|
+
let mut cmd = std::process::Command::new("rustfmt");
|
|
121
|
+
cmd.stderr(std::process::Stdio::inherit());
|
|
122
|
+
cmd.stdout(std::process::Stdio::inherit());
|
|
123
|
+
|
|
124
|
+
cmd.arg(path);
|
|
125
|
+
|
|
126
|
+
if let Err(e) = cmd.status() {
|
|
127
|
+
debug_log!("WARN: failed to run rustfmt: {}", e);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
fn clean_docs(rbconfig: &RbConfig, syntax: &mut syn::File) {
|
|
132
|
+
if rbconfig.is_cross_compiling() {
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
let ver = rbconfig.ruby_version_slug();
|
|
137
|
+
|
|
138
|
+
sanitizer::cleanup_docs(syntax, &ver).unwrap_or_else(|e| {
|
|
139
|
+
debug_log!("WARN: failed to clean up docs, skipping: {}", e);
|
|
140
|
+
})
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
fn default_bindgen(clang_args: Vec<String>, _rbconfig: &RbConfig) -> bindgen::Builder {
|
|
144
|
+
// Disable layout tests and Debug impl on Windows MinGW due to packed struct layout incompatibilities
|
|
145
|
+
let is_windows_mingw = cfg!(target_os = "windows") && !is_msvc();
|
|
146
|
+
|
|
147
|
+
let enable_layout_tests = !is_windows_mingw && cfg!(feature = "bindgen-layout-tests");
|
|
148
|
+
let impl_debug = !is_windows_mingw && cfg!(feature = "bindgen-impl-debug");
|
|
149
|
+
|
|
150
|
+
let mut bindings = bindgen::Builder::default()
|
|
151
|
+
.rustified_enum(".*")
|
|
152
|
+
.no_copy("rb_data_type_struct")
|
|
153
|
+
.derive_eq(true)
|
|
154
|
+
.derive_debug(true)
|
|
155
|
+
.clang_args(clang_args)
|
|
156
|
+
.layout_tests(enable_layout_tests)
|
|
157
|
+
.blocklist_item("^__darwin_pthread.*")
|
|
158
|
+
.blocklist_item("^_opaque_pthread.*")
|
|
159
|
+
.blocklist_item("^__pthread_.*")
|
|
160
|
+
.blocklist_item("^pthread_.*")
|
|
161
|
+
.blocklist_item("^rb_native.*")
|
|
162
|
+
.blocklist_type("INET_PORT_RESERVATION_INSTANCE")
|
|
163
|
+
.blocklist_type("PINET_PORT_RESERVATION_INSTANCE")
|
|
164
|
+
.opaque_type("^__sFILE$")
|
|
165
|
+
.merge_extern_blocks(true)
|
|
166
|
+
.generate_comments(true)
|
|
167
|
+
.size_t_is_usize(env::var("CARGO_FEATURE_BINDGEN_SIZE_T_IS_USIZE").is_ok())
|
|
168
|
+
.impl_debug(impl_debug)
|
|
169
|
+
.parse_callbacks(Box::new(bindgen::CargoCallbacks::new()));
|
|
170
|
+
|
|
171
|
+
// Make __mingw_ldbl_type_t opaque on Windows MinGW to avoid conflicting packed/align representation
|
|
172
|
+
if cfg!(target_os = "windows") && !is_msvc() {
|
|
173
|
+
bindings = bindings.opaque_type("__mingw_ldbl_type_t");
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
if env::var("CARGO_FEATURE_BINDGEN_ENABLE_FUNCTION_ATTRIBUTE_DETECTION").is_ok() {
|
|
177
|
+
bindings.enable_function_attribute_detection()
|
|
178
|
+
} else {
|
|
179
|
+
bindings
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// This is needed because bindgen doesn't support the `__declspec(dllimport)` on
|
|
184
|
+
// global variables. Without it, symbols are not found.
|
|
185
|
+
// See https://stackoverflow.com/a/66182704/2057700
|
|
186
|
+
fn qualify_symbols_for_msvc(tokens: &mut syn::File, is_static: bool, rbconfig: &RbConfig) {
|
|
187
|
+
let kind = if is_static { "static" } else { "dylib" };
|
|
188
|
+
|
|
189
|
+
let name = if is_static {
|
|
190
|
+
rbconfig.libruby_static_name()
|
|
191
|
+
} else {
|
|
192
|
+
rbconfig.libruby_so_name()
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
sanitizer::add_link_ruby_directives(tokens, &name, kind).unwrap_or_else(|e| {
|
|
196
|
+
debug_log!("WARN: failed to add link directives: {}", e);
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// Add things like `#[cfg(ruby_use_transient_heap = "true")]` to the bindings config
|
|
201
|
+
fn push_cargo_cfg_from_bindings(
|
|
202
|
+
syntax: &syn::File,
|
|
203
|
+
cfg_out: &mut File,
|
|
204
|
+
) -> Result<(), Box<dyn Error>> {
|
|
205
|
+
fn is_defines(line: &str) -> bool {
|
|
206
|
+
line.starts_with("HAVE_RUBY")
|
|
207
|
+
|| line.starts_with("HAVE_RB")
|
|
208
|
+
|| line.starts_with("USE")
|
|
209
|
+
|| line.starts_with("RUBY_DEBUG")
|
|
210
|
+
|| line.starts_with("RUBY_NDEBUG")
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
for item in syntax.items.iter() {
|
|
214
|
+
if let syn::Item::Const(item) = item {
|
|
215
|
+
let conf = ConfValue::new(item);
|
|
216
|
+
let conf_name = conf.name();
|
|
217
|
+
|
|
218
|
+
if is_defines(&conf_name) {
|
|
219
|
+
let name = conf_name.to_lowercase();
|
|
220
|
+
let val = conf.value_bool().to_string();
|
|
221
|
+
println!(
|
|
222
|
+
r#"cargo:rustc-check-cfg=cfg(ruby_{}, values("true", "false"))"#,
|
|
223
|
+
name
|
|
224
|
+
);
|
|
225
|
+
println!("cargo:rustc-cfg=ruby_{}=\"{}\"", name, val);
|
|
226
|
+
println!("cargo:defines_{}={}", name, val);
|
|
227
|
+
writeln!(cfg_out, "cargo:defines_{}={}", name, val)?;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
if conf_name.starts_with("RUBY_ABI_VERSION") {
|
|
231
|
+
println!("cargo:ruby_abi_version={}", conf.value_string());
|
|
232
|
+
writeln!(cfg_out, "cargo:ruby_abi_version={}", conf.value_string())?;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
Ok(())
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/// An autoconf constant in the bindings
|
|
241
|
+
struct ConfValue<'a> {
|
|
242
|
+
item: &'a syn::ItemConst,
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
impl<'a> ConfValue<'a> {
|
|
246
|
+
pub fn new(item: &'a ItemConst) -> Self {
|
|
247
|
+
Self { item }
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
pub fn name(&self) -> String {
|
|
251
|
+
self.item.ident.to_string()
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
pub fn value_string(&self) -> String {
|
|
255
|
+
match &*self.item.expr {
|
|
256
|
+
Expr::Lit(ExprLit { lit, .. }) => lit.to_token_stream().to_string(),
|
|
257
|
+
_ => panic!(
|
|
258
|
+
"Could not convert HAVE_* constant to string: {:#?}",
|
|
259
|
+
self.item
|
|
260
|
+
),
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
pub fn value_bool(&self) -> bool {
|
|
265
|
+
match &*self.item.expr {
|
|
266
|
+
Expr::Lit(ExprLit {
|
|
267
|
+
lit: Lit::Int(ref lit),
|
|
268
|
+
..
|
|
269
|
+
}) => lit.base10_parse::<u8>().unwrap_or(1) != 0,
|
|
270
|
+
Expr::Lit(ExprLit {
|
|
271
|
+
lit: Lit::Bool(ref lit),
|
|
272
|
+
..
|
|
273
|
+
}) => lit.value,
|
|
274
|
+
_ => panic!(
|
|
275
|
+
"Could not convert HAVE_* constant to bool: {:#?}",
|
|
276
|
+
self.item
|
|
277
|
+
),
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|