itsi-server 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 +25 -38
- data/Cargo.toml +4 -0
- data/Rakefile +39 -7
- data/ext/itsi_scheduler/Cargo.toml +1 -1
- data/ext/itsi_server/Cargo.toml +1 -1
- data/ext/itsi_server/src/server/signal.rs +7 -5
- data/lib/itsi/server/native_extension.rb +34 -0
- data/lib/itsi/server/version.rb +1 -1
- data/lib/itsi/server.rb +10 -2
- 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 +25 -11
- data/ext/itsi_server/target/release/build/clang-sys-0dae18670e690c25/out/common.rs +0 -355
- data/ext/itsi_server/target/release/build/clang-sys-0dae18670e690c25/out/dynamic.rs +0 -276
- data/ext/itsi_server/target/release/build/clang-sys-0dae18670e690c25/out/macros.rs +0 -49
- data/ext/itsi_server/target/release/build/oid-registry-71b994a322b296ec/out/oid_db.rs +0 -537
- data/ext/itsi_server/target/release/build/rb-sys-9f9831ab50fb86db/out/bindings-0.9.124-mri-arm64-darwin24-2.7.8.rs +0 -6234
- data/ext/itsi_server/target/release/build/rb-sys-9f9831ab50fb86db/out/bindings-0.9.124-mri-arm64-darwin24-3.4.5.rs +0 -8936
- data/ext/itsi_server/target/release/build/rb-sys-9f9831ab50fb86db/out/bindings-0.9.124-mri-arm64-darwin24-4.0.1.rs +0 -9060
- data/ext/itsi_server/target/release/build/typenum-11265e44e46de3b7/out/tests.rs +0 -20563
|
@@ -0,0 +1,906 @@
|
|
|
1
|
+
use std::{
|
|
2
|
+
collections::{hash_map::Keys, HashMap},
|
|
3
|
+
env,
|
|
4
|
+
path::PathBuf,
|
|
5
|
+
process::Command,
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
use regex::Regex;
|
|
9
|
+
mod flags;
|
|
10
|
+
mod library;
|
|
11
|
+
mod search_path;
|
|
12
|
+
|
|
13
|
+
use library::*;
|
|
14
|
+
use search_path::*;
|
|
15
|
+
use std::ffi::OsString;
|
|
16
|
+
|
|
17
|
+
use crate::{
|
|
18
|
+
debug_log, memoize,
|
|
19
|
+
utils::{is_msvc, shellsplit},
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
use self::flags::Flags;
|
|
23
|
+
|
|
24
|
+
/// Extracts structured information from raw compiler/linker flags to make
|
|
25
|
+
/// compiling Ruby gems easier.
|
|
26
|
+
#[derive(Debug, PartialEq, Eq)]
|
|
27
|
+
pub struct RbConfig {
|
|
28
|
+
pub search_paths: Vec<SearchPath>,
|
|
29
|
+
pub libs: Vec<Library>,
|
|
30
|
+
pub link_args: Vec<String>,
|
|
31
|
+
pub cflags: Vec<String>,
|
|
32
|
+
pub blocklist_lib: Vec<String>,
|
|
33
|
+
pub blocklist_link_arg: Vec<String>,
|
|
34
|
+
use_rpath: bool,
|
|
35
|
+
value_map: HashMap<String, String>,
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
impl Default for RbConfig {
|
|
39
|
+
fn default() -> Self {
|
|
40
|
+
Self::new()
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
impl RbConfig {
|
|
45
|
+
/// Creates a new, blank `RbConfig`. You likely want to use `RbConfig::current()` instead.
|
|
46
|
+
pub(crate) fn new() -> RbConfig {
|
|
47
|
+
RbConfig {
|
|
48
|
+
blocklist_lib: vec![],
|
|
49
|
+
blocklist_link_arg: vec![],
|
|
50
|
+
search_paths: Vec::new(),
|
|
51
|
+
libs: Vec::new(),
|
|
52
|
+
link_args: Vec::new(),
|
|
53
|
+
cflags: Vec::new(),
|
|
54
|
+
value_map: HashMap::new(),
|
|
55
|
+
use_rpath: false,
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/// All keys in the `RbConfig`'s value map.
|
|
60
|
+
pub fn all_keys(&self) -> Keys<'_, String, String> {
|
|
61
|
+
self.value_map.keys()
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/// Instantiates a new `RbConfig` for the current Ruby.
|
|
65
|
+
pub fn current() -> RbConfig {
|
|
66
|
+
println!("cargo:rerun-if-env-changed=RUBY");
|
|
67
|
+
|
|
68
|
+
let mut rbconfig = RbConfig::new();
|
|
69
|
+
|
|
70
|
+
// Never use the current Ruby's RbConfig if we're cross compiling, or
|
|
71
|
+
// else bad things happen
|
|
72
|
+
let parsed = if rbconfig.is_cross_compiling() {
|
|
73
|
+
HashMap::new()
|
|
74
|
+
} else {
|
|
75
|
+
let output = memoize!(String: {
|
|
76
|
+
let ruby = env::var_os("RUBY").unwrap_or_else(|| OsString::from("ruby"));
|
|
77
|
+
|
|
78
|
+
let config = Command::new(ruby)
|
|
79
|
+
.arg("--disable-gems")
|
|
80
|
+
.arg("-rrbconfig")
|
|
81
|
+
.arg("-e")
|
|
82
|
+
.arg("print RbConfig::CONFIG.map {|kv| kv.join(\"\x1F\")}.join(\"\x1E\")")
|
|
83
|
+
.output()
|
|
84
|
+
.unwrap_or_else(|e| panic!("ruby not found: {}", e));
|
|
85
|
+
if !config.status.success() {
|
|
86
|
+
panic!("non-zero exit status while dumping RbConfig: {:?}", config);
|
|
87
|
+
}
|
|
88
|
+
String::from_utf8(config.stdout).expect("RbConfig value not UTF-8!")
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
let mut parsed = HashMap::new();
|
|
92
|
+
for line in output.split('\x1E') {
|
|
93
|
+
let mut parts = line.splitn(2, '\x1F');
|
|
94
|
+
if let (Some(key), Some(val)) = (parts.next(), parts.next()) {
|
|
95
|
+
parsed.insert(key.to_owned(), val.to_owned());
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
parsed
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
parsed.get("cflags").map(|f| rbconfig.push_cflags(f));
|
|
102
|
+
parsed.get("DLDFLAGS").map(|f| rbconfig.push_dldflags(f));
|
|
103
|
+
|
|
104
|
+
rbconfig.value_map = parsed;
|
|
105
|
+
|
|
106
|
+
rbconfig
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/// Pushes the `LIBRUBYARG` flags so Ruby will be linked.
|
|
110
|
+
pub fn link_ruby(&mut self, is_static: bool) -> &mut Self {
|
|
111
|
+
let Some(libdir) = self.get("libdir") else {
|
|
112
|
+
return self;
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
self.push_search_path(libdir.as_str());
|
|
116
|
+
self.push_dldflags(&format!("-L{}", libdir));
|
|
117
|
+
|
|
118
|
+
let librubyarg = if is_static {
|
|
119
|
+
self.get("LIBRUBYARG_STATIC")
|
|
120
|
+
} else {
|
|
121
|
+
self.get("LIBRUBYARG_SHARED")
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
let librubyarg = match librubyarg {
|
|
125
|
+
Some(lib) => lib,
|
|
126
|
+
None => {
|
|
127
|
+
debug_log!("WARN: LIBRUBYARG not found in RbConfig, skipping linking Ruby");
|
|
128
|
+
return self;
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
if is_msvc() {
|
|
133
|
+
for lib in librubyarg.split_whitespace() {
|
|
134
|
+
self.push_library(lib);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
let mut to_link: Vec<String> = vec![];
|
|
138
|
+
|
|
139
|
+
if let Some(libs) = self.get("LIBS") {
|
|
140
|
+
to_link.extend(libs.split_whitespace().map(|s| s.to_string()));
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if let Some(libs) = self.get("LOCAL_LIBS") {
|
|
144
|
+
to_link.extend(libs.split_whitespace().map(|s| s.to_string()));
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
for lib in to_link {
|
|
148
|
+
self.push_library(lib);
|
|
149
|
+
}
|
|
150
|
+
} else {
|
|
151
|
+
self.push_dldflags(&librubyarg);
|
|
152
|
+
|
|
153
|
+
if cfg!(unix) {
|
|
154
|
+
self.use_rpath();
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
self
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/// Get the name for libruby-static (i.e. `ruby.3.1-static`).
|
|
162
|
+
pub fn libruby_static_name(&self) -> String {
|
|
163
|
+
let Some(lib) = self.get("LIBRUBY_A") else {
|
|
164
|
+
return format!("{}-static", self.libruby_so_name());
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
lib.trim_start_matches("lib")
|
|
168
|
+
.trim_end_matches(".a")
|
|
169
|
+
.to_string()
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/// Get the name for libruby (i.e. `ruby.3.1`)
|
|
173
|
+
pub fn libruby_so_name(&self) -> String {
|
|
174
|
+
self.get("RUBY_SO_NAME")
|
|
175
|
+
.unwrap_or_else(|| "ruby".to_string())
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/// Get the platform for the current ruby.
|
|
179
|
+
pub fn platform(&self) -> String {
|
|
180
|
+
self.get("platform")
|
|
181
|
+
.unwrap_or_else(|| self.get("arch").expect("arch not found"))
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/// Filter the libs, removing the ones that are not needed.
|
|
185
|
+
pub fn blocklist_lib(&mut self, name: &str) -> &mut RbConfig {
|
|
186
|
+
self.blocklist_lib.push(name.to_string());
|
|
187
|
+
self
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/// Blocklist a link argument.
|
|
191
|
+
pub fn blocklist_link_arg(&mut self, name: &str) -> &mut RbConfig {
|
|
192
|
+
self.blocklist_link_arg.push(name.to_string());
|
|
193
|
+
self
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/// Returns the current ruby program version.
|
|
197
|
+
pub fn ruby_version_slug(&self) -> String {
|
|
198
|
+
let ver = if let Some(progv) = self.get("RUBY_PROGRAM_VERSION") {
|
|
199
|
+
progv
|
|
200
|
+
} else if let Some(major_minor) = self.major_minor() {
|
|
201
|
+
format!(
|
|
202
|
+
"{}.{}.{}",
|
|
203
|
+
major_minor.0,
|
|
204
|
+
major_minor.1,
|
|
205
|
+
self.get("TEENY").unwrap_or_else(|| "0".to_string())
|
|
206
|
+
)
|
|
207
|
+
} else if let Some(fallback) = self.get("ruby_version") {
|
|
208
|
+
fallback
|
|
209
|
+
} else {
|
|
210
|
+
panic!("RUBY_PROGRAM_VERSION not found")
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
format!("{}-{}-{}", self.ruby_engine(), self.platform(), ver)
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/// Get the CPPFLAGS from the RbConfig, making sure to subsitute variables.
|
|
217
|
+
pub fn cppflags(&self) -> Vec<String> {
|
|
218
|
+
if let Some(cppflags) = self.get("CPPFLAGS") {
|
|
219
|
+
let flags = self.subst_shell_variables(&cppflags);
|
|
220
|
+
shellsplit(flags)
|
|
221
|
+
} else {
|
|
222
|
+
vec![]
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/// Returns true if the current Ruby is cross compiling.
|
|
227
|
+
pub fn is_cross_compiling(&self) -> bool {
|
|
228
|
+
if let Some(cross) = self.get("CROSS_COMPILING") {
|
|
229
|
+
cross == "yes" || cross == "1"
|
|
230
|
+
} else {
|
|
231
|
+
false
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/// Returns the value of the given key from the either the matching
|
|
236
|
+
/// `RBCONFIG_{key}` environment variable or `RbConfig::CONFIG[{key}]` hash.
|
|
237
|
+
pub fn get(&self, key: &str) -> Option<String> {
|
|
238
|
+
self.try_rbconfig_env(key)
|
|
239
|
+
.or_else(|| self.try_value_map(key))
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/// Enables the use of rpath for linking.
|
|
243
|
+
pub fn use_rpath(&mut self) -> &mut RbConfig {
|
|
244
|
+
self.use_rpath = true;
|
|
245
|
+
self
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/// Push cflags string
|
|
249
|
+
pub fn push_cflags(&mut self, cflags: &str) -> &mut Self {
|
|
250
|
+
for flag in shellsplit(cflags) {
|
|
251
|
+
if !self.cflags.contains(&flag) {
|
|
252
|
+
self.cflags.push(flag.to_string());
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
self
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/// Get major/minor version tuple of Ruby
|
|
260
|
+
pub fn major_minor(&self) -> Option<(u32, u32)> {
|
|
261
|
+
let major = self.get("MAJOR").map(|v| v.parse::<u32>())?.ok()?;
|
|
262
|
+
let minor = self.get("MINOR").map(|v| v.parse::<u32>())?.ok()?;
|
|
263
|
+
Some((major, minor))
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/// Get the rb_config output for cargo
|
|
267
|
+
pub fn cargo_args(&self) -> Vec<String> {
|
|
268
|
+
let mut result = vec![];
|
|
269
|
+
|
|
270
|
+
let mut search_paths = vec![];
|
|
271
|
+
|
|
272
|
+
for search_path in &self.search_paths {
|
|
273
|
+
result.push(format!("cargo:rustc-link-search={}", search_path));
|
|
274
|
+
search_paths.push(search_path.name.as_str());
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
for lib in &self.libs {
|
|
278
|
+
if !self.blocklist_lib.iter().any(|b| lib.name.contains(b)) {
|
|
279
|
+
result.push(format!("cargo:rustc-link-lib={}", lib));
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
if self.use_rpath && !lib.is_static() {
|
|
283
|
+
result.push(format!("cargo:rustc-link-arg=-Wl,-rpath,{}", lib));
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
for link_arg in &self.link_args {
|
|
288
|
+
if !self.blocklist_link_arg.iter().any(|b| link_arg == b) {
|
|
289
|
+
result.push(format!("cargo:rustc-link-arg={}", link_arg));
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
result
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/// Print to rb_config output for cargo
|
|
297
|
+
pub fn print_cargo_args(&self) {
|
|
298
|
+
let cargo_args = self.cargo_args();
|
|
299
|
+
|
|
300
|
+
for arg in &cargo_args {
|
|
301
|
+
println!("{}", arg);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
debug_log!("INFO: printing cargo args ({:?})", cargo_args);
|
|
305
|
+
|
|
306
|
+
let encoded_cargo_args = cargo_args.join("\x1E");
|
|
307
|
+
let encoded_cargo_args = encoded_cargo_args.replace('\n', "\x1F");
|
|
308
|
+
|
|
309
|
+
println!("cargo:encoded_cargo_args={}", encoded_cargo_args);
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
/// Adds items to the rb_config based on a string from LDFLAGS/DLDFLAGS
|
|
313
|
+
pub fn push_dldflags(&mut self, input: &str) -> &mut Self {
|
|
314
|
+
let input = self.subst_shell_variables(input);
|
|
315
|
+
let split_args = Flags::new(input.as_str());
|
|
316
|
+
|
|
317
|
+
let search_path_regex = Regex::new(r"^-L\s*(?P<name>.*)$").unwrap();
|
|
318
|
+
let lib_regex_short = Regex::new(r"^-l\s*(?P<name>\w+\S+)$").unwrap();
|
|
319
|
+
let lib_regex_long = Regex::new(r"^--library=(?P<name>\w+\S+)$").unwrap();
|
|
320
|
+
let dynamic_lib_regex = Regex::new(r"^-l\s*:lib(?P<name>\S+).(so|dylib|dll)$").unwrap();
|
|
321
|
+
let framework_regex_short = Regex::new(r"^-F\s*(?P<name>.*)$").unwrap();
|
|
322
|
+
let framework_regex_long = Regex::new(r"^-framework\s*(?P<name>.*)$").unwrap();
|
|
323
|
+
|
|
324
|
+
for arg in split_args {
|
|
325
|
+
let arg = arg.trim().to_owned();
|
|
326
|
+
|
|
327
|
+
if let Some(name) = capture_name(&search_path_regex, &arg) {
|
|
328
|
+
self.push_search_path(name.as_str());
|
|
329
|
+
} else if let Some(name) = capture_name(&lib_regex_long, &arg) {
|
|
330
|
+
self.push_library(name);
|
|
331
|
+
} else if let Some(name) = capture_name(&lib_regex_short, &arg) {
|
|
332
|
+
if name.contains("ruby") && name.contains("-static") {
|
|
333
|
+
self.push_library((LibraryKind::Static, name));
|
|
334
|
+
} else {
|
|
335
|
+
self.push_library(name);
|
|
336
|
+
}
|
|
337
|
+
} else if let Some(name) = capture_name(&dynamic_lib_regex, &arg) {
|
|
338
|
+
self.push_library((LibraryKind::Dylib, name));
|
|
339
|
+
} else if let Some(name) = capture_name(&framework_regex_short, &arg) {
|
|
340
|
+
self.push_search_path((SearchPathKind::Framework, name));
|
|
341
|
+
} else if let Some(name) = capture_name(&framework_regex_long, &arg) {
|
|
342
|
+
self.push_library((LibraryKind::Framework, name));
|
|
343
|
+
} else {
|
|
344
|
+
self.push_link_arg(arg);
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
self
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
/// Sets a value for a key
|
|
352
|
+
pub fn set_value_for_key(&mut self, key: &str, value: String) {
|
|
353
|
+
self.value_map.insert(key.to_owned(), value);
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
// Check if has ABI version
|
|
357
|
+
pub fn has_ruby_dln_check_abi(&self) -> bool {
|
|
358
|
+
let Some((major, minor)) = self.major_minor() else {
|
|
359
|
+
return false;
|
|
360
|
+
};
|
|
361
|
+
|
|
362
|
+
let patchlevel = self
|
|
363
|
+
.get("PATCHLEVEL")
|
|
364
|
+
.and_then(|v| v.parse::<i32>().ok())
|
|
365
|
+
.unwrap_or(-1);
|
|
366
|
+
|
|
367
|
+
// Ruby has ABI version on version 3.2 and later only on development
|
|
368
|
+
// versions
|
|
369
|
+
(major > 3 || (major == 3 && minor >= 2))
|
|
370
|
+
&& patchlevel == -1
|
|
371
|
+
&& !cfg!(target_family = "windows")
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
/// The RUBY_ENGINE we are building for
|
|
375
|
+
pub fn ruby_engine(&self) -> RubyEngine {
|
|
376
|
+
if let Some(engine) = self.get("ruby_install_name") {
|
|
377
|
+
match engine.as_str() {
|
|
378
|
+
"ruby" => RubyEngine::Mri,
|
|
379
|
+
"jruby" => RubyEngine::JRuby,
|
|
380
|
+
"truffleruby" => RubyEngine::TruffleRuby,
|
|
381
|
+
_ => RubyEngine::Mri, // not sure how stable this is, so default to MRI to avoid breaking things
|
|
382
|
+
}
|
|
383
|
+
} else {
|
|
384
|
+
RubyEngine::Mri
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
// Examines the string from shell variables and expands them with values in the value_map
|
|
389
|
+
fn subst_shell_variables(&self, input: &str) -> String {
|
|
390
|
+
let mut result = String::new();
|
|
391
|
+
let mut chars = input.chars().enumerate();
|
|
392
|
+
|
|
393
|
+
while let Some((_, c)) = chars.next() {
|
|
394
|
+
if c == '$' {
|
|
395
|
+
if let Some((i, c)) = chars.next() {
|
|
396
|
+
if c == '(' {
|
|
397
|
+
let start = i + 1;
|
|
398
|
+
let mut end = start;
|
|
399
|
+
|
|
400
|
+
for (i, c) in chars.by_ref() {
|
|
401
|
+
if c == ')' {
|
|
402
|
+
end = i;
|
|
403
|
+
break;
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
let key = &input[start..end];
|
|
408
|
+
|
|
409
|
+
if let Some(val) = self.get(key) {
|
|
410
|
+
result.push_str(&val);
|
|
411
|
+
} else if let Some(val) = env::var_os(key) {
|
|
412
|
+
result.push_str(&val.to_string_lossy());
|
|
413
|
+
} else {
|
|
414
|
+
// Consume whitespace
|
|
415
|
+
chars.next();
|
|
416
|
+
}
|
|
417
|
+
} else {
|
|
418
|
+
result.push(c);
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
} else {
|
|
422
|
+
result.push(c);
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
result
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
pub fn have_ruby_header<T: AsRef<str>>(&self, header: T) -> bool {
|
|
430
|
+
let Some(ruby_include_dir) = self.get("rubyhdrdir") else {
|
|
431
|
+
return false;
|
|
432
|
+
};
|
|
433
|
+
PathBuf::from(ruby_include_dir)
|
|
434
|
+
.join(header.as_ref())
|
|
435
|
+
.exists()
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
fn push_search_path<T: Into<SearchPath>>(&mut self, path: T) -> &mut Self {
|
|
439
|
+
let path = path.into();
|
|
440
|
+
|
|
441
|
+
if !self.search_paths.contains(&path) {
|
|
442
|
+
self.search_paths.push(path);
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
self
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
fn push_library<T: Into<Library>>(&mut self, lib: T) -> &mut Self {
|
|
449
|
+
let lib = lib.into();
|
|
450
|
+
|
|
451
|
+
if !self.libs.contains(&lib) {
|
|
452
|
+
self.libs.push(lib);
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
self
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
fn push_link_arg<T: Into<String>>(&mut self, arg: T) -> &mut Self {
|
|
459
|
+
let arg = arg.into();
|
|
460
|
+
|
|
461
|
+
if !self.link_args.contains(&arg) {
|
|
462
|
+
self.link_args.push(arg);
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
self
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
fn try_value_map(&self, key: &str) -> Option<String> {
|
|
469
|
+
self.value_map
|
|
470
|
+
.get(key)
|
|
471
|
+
.map(|val| val.trim_matches('\n').to_owned())
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
fn try_rbconfig_env(&self, key: &str) -> Option<String> {
|
|
475
|
+
let key = format!("RBCONFIG_{}", key);
|
|
476
|
+
println!("cargo:rerun-if-env-changed={}", key);
|
|
477
|
+
env::var(key).map(|v| v.trim_matches('\n').to_owned()).ok()
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
|
482
|
+
pub enum RubyEngine {
|
|
483
|
+
Mri,
|
|
484
|
+
TruffleRuby,
|
|
485
|
+
JRuby,
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
impl std::fmt::Display for RubyEngine {
|
|
489
|
+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
490
|
+
match self {
|
|
491
|
+
RubyEngine::Mri => write!(f, "mri"),
|
|
492
|
+
RubyEngine::TruffleRuby => write!(f, "truffleruby"),
|
|
493
|
+
RubyEngine::JRuby => write!(f, "jruby"),
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
fn capture_name(regex: &Regex, arg: &str) -> Option<String> {
|
|
499
|
+
regex
|
|
500
|
+
.captures(arg)
|
|
501
|
+
.map(|cap| cap.name("name").unwrap().as_str().trim().to_owned())
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
#[cfg(test)]
|
|
505
|
+
mod tests {
|
|
506
|
+
use super::*;
|
|
507
|
+
use std::{sync::Mutex, vec};
|
|
508
|
+
|
|
509
|
+
lazy_static::lazy_static! {
|
|
510
|
+
static ref ENV_LOCK: Mutex<()> = Mutex::new(());
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
fn with_locked_env<F, T>(f: F) -> T
|
|
514
|
+
where
|
|
515
|
+
F: FnOnce() -> T,
|
|
516
|
+
{
|
|
517
|
+
let _guard = ENV_LOCK.lock().unwrap();
|
|
518
|
+
f()
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
#[test]
|
|
522
|
+
fn test_extract_lib_search_paths() {
|
|
523
|
+
let mut rb_config = RbConfig::new();
|
|
524
|
+
rb_config.push_dldflags("-L/usr/local/lib -L/usr/lib");
|
|
525
|
+
assert_eq!(
|
|
526
|
+
rb_config.search_paths,
|
|
527
|
+
vec!["/usr/local/lib".into(), "/usr/lib".into()]
|
|
528
|
+
);
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
#[test]
|
|
532
|
+
fn test_search_path_basic() {
|
|
533
|
+
let mut rb_config = RbConfig::new();
|
|
534
|
+
rb_config.push_dldflags("-L/usr/local/lib");
|
|
535
|
+
|
|
536
|
+
assert_eq!(rb_config.search_paths, vec!["native=/usr/local/lib".into()]);
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
#[test]
|
|
540
|
+
fn test_search_path_space() {
|
|
541
|
+
let mut rb_config = RbConfig::new();
|
|
542
|
+
rb_config.push_dldflags("-L /usr/local/lib");
|
|
543
|
+
|
|
544
|
+
assert_eq!(rb_config.search_paths, vec!["/usr/local/lib".into()]);
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
#[test]
|
|
548
|
+
fn test_search_path_space_in_path() {
|
|
549
|
+
let mut rb_config = RbConfig::new();
|
|
550
|
+
rb_config.push_dldflags("-L/usr/local/my lib");
|
|
551
|
+
|
|
552
|
+
assert_eq!(
|
|
553
|
+
rb_config.search_paths,
|
|
554
|
+
vec!["native=/usr/local/my lib".into()]
|
|
555
|
+
);
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
#[test]
|
|
559
|
+
fn test_simple_lib() {
|
|
560
|
+
let mut rb_config = RbConfig::new();
|
|
561
|
+
rb_config.push_dldflags("-lfoo");
|
|
562
|
+
|
|
563
|
+
assert_eq!(rb_config.libs, ["foo".into()]);
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
#[test]
|
|
567
|
+
fn test_lib_with_nonascii() {
|
|
568
|
+
let mut rb_config = RbConfig::new();
|
|
569
|
+
rb_config.push_dldflags("-lws2_32");
|
|
570
|
+
|
|
571
|
+
assert_eq!(rb_config.libs, ["ws2_32".into()]);
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
#[test]
|
|
575
|
+
fn test_simple_lib_space() {
|
|
576
|
+
let mut rb_config = RbConfig::new();
|
|
577
|
+
rb_config.push_dldflags("-l foo");
|
|
578
|
+
|
|
579
|
+
assert_eq!(rb_config.libs, ["foo".into()]);
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
#[test]
|
|
583
|
+
fn test_verbose_lib_space() {
|
|
584
|
+
let mut rb_config = RbConfig::new();
|
|
585
|
+
rb_config.push_dldflags("--library=foo");
|
|
586
|
+
|
|
587
|
+
assert_eq!(rb_config.libs, ["foo".into()]);
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
#[test]
|
|
591
|
+
fn test_dylib_with_colon_space() {
|
|
592
|
+
let mut rb_config = RbConfig::new();
|
|
593
|
+
rb_config.push_dldflags("-l :libssp.dylib");
|
|
594
|
+
|
|
595
|
+
assert_eq!(rb_config.libs, ["dylib=ssp".into()]);
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
#[test]
|
|
599
|
+
fn test_so_with_colon_space() {
|
|
600
|
+
let mut rb_config = RbConfig::new();
|
|
601
|
+
rb_config.push_dldflags("-l :libssp.so");
|
|
602
|
+
|
|
603
|
+
assert_eq!(rb_config.libs, ["dylib=ssp".into()]);
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
#[test]
|
|
607
|
+
fn test_dll_with_colon_space() {
|
|
608
|
+
let mut rb_config = RbConfig::new();
|
|
609
|
+
rb_config.push_dldflags("-l :libssp.dll");
|
|
610
|
+
|
|
611
|
+
assert_eq!(rb_config.libs, ["dylib=ssp".into()]);
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
#[test]
|
|
615
|
+
fn test_framework() {
|
|
616
|
+
let mut rb_config = RbConfig::new();
|
|
617
|
+
rb_config.push_dldflags("-F/some/path");
|
|
618
|
+
|
|
619
|
+
assert_eq!(rb_config.search_paths, ["framework=/some/path".into()]);
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
#[test]
|
|
623
|
+
fn test_framework_space() {
|
|
624
|
+
let mut rb_config = RbConfig::new();
|
|
625
|
+
rb_config.push_dldflags("-F /some/path");
|
|
626
|
+
|
|
627
|
+
assert_eq!(
|
|
628
|
+
rb_config.search_paths,
|
|
629
|
+
[SearchPath {
|
|
630
|
+
kind: SearchPathKind::Framework,
|
|
631
|
+
name: "/some/path".into(),
|
|
632
|
+
}]
|
|
633
|
+
);
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
#[test]
|
|
637
|
+
fn test_framework_arg_real() {
|
|
638
|
+
let mut rb_config = RbConfig::new();
|
|
639
|
+
rb_config.push_dldflags("-framework CoreFoundation");
|
|
640
|
+
|
|
641
|
+
assert_eq!(
|
|
642
|
+
rb_config.libs,
|
|
643
|
+
[Library {
|
|
644
|
+
kind: LibraryKind::Framework,
|
|
645
|
+
name: "CoreFoundation".into(),
|
|
646
|
+
}]
|
|
647
|
+
);
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
#[test]
|
|
651
|
+
fn test_libruby_static() {
|
|
652
|
+
let mut rb_config = RbConfig::new();
|
|
653
|
+
rb_config.push_dldflags("-lruby.3.1-static");
|
|
654
|
+
|
|
655
|
+
assert_eq!(
|
|
656
|
+
rb_config.cargo_args(),
|
|
657
|
+
["cargo:rustc-link-lib=static=ruby.3.1-static"]
|
|
658
|
+
);
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
#[test]
|
|
662
|
+
fn test_libruby_dynamic() {
|
|
663
|
+
let mut rb_config = RbConfig::new();
|
|
664
|
+
rb_config.push_dldflags("-lruby.3.1");
|
|
665
|
+
|
|
666
|
+
assert_eq!(rb_config.cargo_args(), ["cargo:rustc-link-lib=ruby.3.1"]);
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
#[test]
|
|
670
|
+
fn test_non_lib_dash_l() {
|
|
671
|
+
let mut rb_config = RbConfig::new();
|
|
672
|
+
rb_config.push_dldflags("test_rubygems_20220413-976-lemgf9/prefix");
|
|
673
|
+
|
|
674
|
+
assert_eq!(
|
|
675
|
+
rb_config.link_args,
|
|
676
|
+
vec!["test_rubygems_20220413-976-lemgf9/prefix"]
|
|
677
|
+
);
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
#[test]
|
|
681
|
+
fn test_real_dldflags() {
|
|
682
|
+
let mut rb_config = RbConfig::new();
|
|
683
|
+
rb_config.push_dldflags("-L/Users/ianks/.asdf/installs/ruby/3.1.1/lib -L/opt/homebrew/opt/openssl@1.1/lib -Wl,-undefined,dynamic_lookup -Wl,-multiply_defined,suppress");
|
|
684
|
+
|
|
685
|
+
assert_eq!(
|
|
686
|
+
rb_config.link_args,
|
|
687
|
+
vec![
|
|
688
|
+
"-Wl,-undefined,dynamic_lookup",
|
|
689
|
+
"-Wl,-multiply_defined,suppress"
|
|
690
|
+
]
|
|
691
|
+
);
|
|
692
|
+
assert_eq!(
|
|
693
|
+
rb_config.search_paths,
|
|
694
|
+
vec![
|
|
695
|
+
SearchPath {
|
|
696
|
+
kind: SearchPathKind::Native,
|
|
697
|
+
name: "/Users/ianks/.asdf/installs/ruby/3.1.1/lib".to_string()
|
|
698
|
+
},
|
|
699
|
+
SearchPath {
|
|
700
|
+
kind: SearchPathKind::Native,
|
|
701
|
+
name: "/opt/homebrew/opt/openssl@1.1/lib".to_string()
|
|
702
|
+
},
|
|
703
|
+
]
|
|
704
|
+
);
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
#[test]
|
|
708
|
+
fn test_crazy_cases() {
|
|
709
|
+
let mut rb_config = RbConfig::new();
|
|
710
|
+
rb_config.push_dldflags("-F /something -l:libssp.a -static-libgcc ");
|
|
711
|
+
|
|
712
|
+
assert_eq!(rb_config.link_args, vec!["-l:libssp.a", "-static-libgcc"]);
|
|
713
|
+
assert_eq!(
|
|
714
|
+
rb_config.search_paths,
|
|
715
|
+
vec![SearchPath {
|
|
716
|
+
kind: SearchPathKind::Framework,
|
|
717
|
+
name: "/something".to_string()
|
|
718
|
+
},]
|
|
719
|
+
);
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
#[test]
|
|
723
|
+
fn test_printing_cargo_args() {
|
|
724
|
+
let mut rb_config = RbConfig::new();
|
|
725
|
+
rb_config.push_dldflags("-L/Users/ianks/.asdf/installs/ruby/3.1.1/lib");
|
|
726
|
+
rb_config.push_dldflags("-lfoo");
|
|
727
|
+
rb_config.push_dldflags("-static-libgcc");
|
|
728
|
+
let result = rb_config.cargo_args();
|
|
729
|
+
|
|
730
|
+
assert_eq!(
|
|
731
|
+
vec![
|
|
732
|
+
"cargo:rustc-link-search=native=/Users/ianks/.asdf/installs/ruby/3.1.1/lib",
|
|
733
|
+
"cargo:rustc-link-lib=foo",
|
|
734
|
+
"cargo:rustc-link-arg=-static-libgcc"
|
|
735
|
+
],
|
|
736
|
+
result
|
|
737
|
+
);
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
#[test]
|
|
741
|
+
fn test_use_rpath() {
|
|
742
|
+
let mut rb_config = RbConfig::new();
|
|
743
|
+
rb_config.push_dldflags("-lfoo");
|
|
744
|
+
|
|
745
|
+
assert_eq!(vec!["cargo:rustc-link-lib=foo"], rb_config.cargo_args());
|
|
746
|
+
|
|
747
|
+
rb_config.use_rpath();
|
|
748
|
+
|
|
749
|
+
assert_eq!(
|
|
750
|
+
vec![
|
|
751
|
+
"cargo:rustc-link-lib=foo",
|
|
752
|
+
"cargo:rustc-link-arg=-Wl,-rpath,foo"
|
|
753
|
+
],
|
|
754
|
+
rb_config.cargo_args()
|
|
755
|
+
);
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
#[test]
|
|
759
|
+
fn test_link_mswin() {
|
|
760
|
+
with_locked_env(|| {
|
|
761
|
+
let old_var = env::var("TARGET").ok();
|
|
762
|
+
env::set_var("TARGET", "x86_64-pc-windows-msvc");
|
|
763
|
+
|
|
764
|
+
let mut rb_config = RbConfig::new();
|
|
765
|
+
rb_config.set_value_for_key("LIBRUBYARG_SHARED", "x64-vcruntime140-ruby320.lib".into());
|
|
766
|
+
rb_config.set_value_for_key("libdir", "D:/ruby-mswin/lib".into());
|
|
767
|
+
rb_config.set_value_for_key("LIBS", "user32.lib".into());
|
|
768
|
+
rb_config.link_ruby(false);
|
|
769
|
+
|
|
770
|
+
assert_eq!(
|
|
771
|
+
vec![
|
|
772
|
+
"cargo:rustc-link-search=native=D:/ruby-mswin/lib",
|
|
773
|
+
"cargo:rustc-link-lib=x64-vcruntime140-ruby320",
|
|
774
|
+
"cargo:rustc-link-lib=user32",
|
|
775
|
+
],
|
|
776
|
+
rb_config.cargo_args()
|
|
777
|
+
);
|
|
778
|
+
|
|
779
|
+
if let Some(old_var) = old_var {
|
|
780
|
+
env::set_var("TARGET", old_var);
|
|
781
|
+
} else {
|
|
782
|
+
env::remove_var("TARGET");
|
|
783
|
+
}
|
|
784
|
+
})
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
#[test]
|
|
788
|
+
fn test_link_static() {
|
|
789
|
+
with_locked_env(|| {
|
|
790
|
+
let mut rb_config = RbConfig::new();
|
|
791
|
+
rb_config.set_value_for_key("LIBRUBYARG_STATIC", "-lruby-static".into());
|
|
792
|
+
rb_config.set_value_for_key("libdir", "/opt/ruby".into());
|
|
793
|
+
|
|
794
|
+
rb_config.link_ruby(true);
|
|
795
|
+
|
|
796
|
+
assert_eq!(
|
|
797
|
+
vec![
|
|
798
|
+
"cargo:rustc-link-search=native=/opt/ruby",
|
|
799
|
+
"cargo:rustc-link-lib=static=ruby-static",
|
|
800
|
+
],
|
|
801
|
+
rb_config.cargo_args()
|
|
802
|
+
);
|
|
803
|
+
});
|
|
804
|
+
}
|
|
805
|
+
|
|
806
|
+
#[test]
|
|
807
|
+
fn test_prioritizes_rbconfig_env() {
|
|
808
|
+
with_locked_env(|| {
|
|
809
|
+
env::set_var("RBCONFIG_libdir", "/foo");
|
|
810
|
+
let rb_config = RbConfig::new();
|
|
811
|
+
|
|
812
|
+
assert_eq!(rb_config.get("libdir"), Some("/foo".into()));
|
|
813
|
+
|
|
814
|
+
env::remove_var("RBCONFIG_libdir");
|
|
815
|
+
});
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
#[test]
|
|
819
|
+
fn test_never_loads_shell_rbconfig_if_cross_compiling() {
|
|
820
|
+
with_locked_env(|| {
|
|
821
|
+
env::set_var("RBCONFIG_CROSS_COMPILING", "yes");
|
|
822
|
+
|
|
823
|
+
let rb_config = RbConfig::current();
|
|
824
|
+
|
|
825
|
+
assert!(rb_config.value_map.is_empty());
|
|
826
|
+
});
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
#[test]
|
|
830
|
+
fn test_loads_shell_rbconfig_if_not_cross_compiling() {
|
|
831
|
+
with_locked_env(|| {
|
|
832
|
+
env::set_var("RBCONFIG_CROSS_COMPILING", "no");
|
|
833
|
+
|
|
834
|
+
let rb_config = RbConfig::current();
|
|
835
|
+
|
|
836
|
+
assert!(!rb_config.value_map.is_empty());
|
|
837
|
+
});
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
#[test]
|
|
841
|
+
fn test_libstatic() {
|
|
842
|
+
let mut rb_config = RbConfig::new();
|
|
843
|
+
rb_config.push_dldflags("-l:libssp.a");
|
|
844
|
+
|
|
845
|
+
assert_eq!(rb_config.link_args, ["-l:libssp.a".to_string()]);
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
#[test]
|
|
849
|
+
fn test_link_arg_blocklist() {
|
|
850
|
+
let mut rb_config = RbConfig::new();
|
|
851
|
+
rb_config.blocklist_link_arg("-Wl,--compress-debug-sections=zlib");
|
|
852
|
+
rb_config.blocklist_link_arg("-s");
|
|
853
|
+
rb_config.push_dldflags(
|
|
854
|
+
"-lfoo -Wl,--compress-debug-sections=zlib -s -somethingthatshouldnotbeblocked",
|
|
855
|
+
);
|
|
856
|
+
|
|
857
|
+
assert_eq!(
|
|
858
|
+
vec![
|
|
859
|
+
"cargo:rustc-link-lib=foo",
|
|
860
|
+
"cargo:rustc-link-arg=-somethingthatshouldnotbeblocked"
|
|
861
|
+
],
|
|
862
|
+
rb_config.cargo_args()
|
|
863
|
+
);
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
#[test]
|
|
867
|
+
fn test_has_ruby_dln_check_abi() {
|
|
868
|
+
// Helper to create RbConfig with specific version
|
|
869
|
+
fn make_config(major: &str, minor: &str, patchlevel: &str) -> RbConfig {
|
|
870
|
+
let mut rb_config = RbConfig::new();
|
|
871
|
+
rb_config.set_value_for_key("MAJOR", major.into());
|
|
872
|
+
rb_config.set_value_for_key("MINOR", minor.into());
|
|
873
|
+
rb_config.set_value_for_key("PATCHLEVEL", patchlevel.into());
|
|
874
|
+
rb_config
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
// Ruby 3.1.x (any patchlevel) - too old
|
|
878
|
+
assert!(!make_config("3", "1", "-1").has_ruby_dln_check_abi());
|
|
879
|
+
assert!(!make_config("3", "1", "0").has_ruby_dln_check_abi());
|
|
880
|
+
|
|
881
|
+
// Ruby 3.2.0-dev (patchlevel -1) - should have ABI check
|
|
882
|
+
#[cfg(not(target_family = "windows"))]
|
|
883
|
+
assert!(make_config("3", "2", "-1").has_ruby_dln_check_abi());
|
|
884
|
+
|
|
885
|
+
// Ruby 3.2.0 release (patchlevel 0) - no ABI check
|
|
886
|
+
assert!(!make_config("3", "2", "0").has_ruby_dln_check_abi());
|
|
887
|
+
|
|
888
|
+
// Ruby 3.3.0-dev - should have ABI check
|
|
889
|
+
#[cfg(not(target_family = "windows"))]
|
|
890
|
+
assert!(make_config("3", "3", "-1").has_ruby_dln_check_abi());
|
|
891
|
+
|
|
892
|
+
// Ruby 4.0.0-dev - should have ABI check (this was the bug!)
|
|
893
|
+
#[cfg(not(target_family = "windows"))]
|
|
894
|
+
assert!(make_config("4", "0", "-1").has_ruby_dln_check_abi());
|
|
895
|
+
|
|
896
|
+
// Ruby 4.0.0 release - no ABI check
|
|
897
|
+
assert!(!make_config("4", "0", "0").has_ruby_dln_check_abi());
|
|
898
|
+
|
|
899
|
+
// Ruby 4.1.0-dev - should have ABI check
|
|
900
|
+
#[cfg(not(target_family = "windows"))]
|
|
901
|
+
assert!(make_config("4", "1", "-1").has_ruby_dln_check_abi());
|
|
902
|
+
|
|
903
|
+
// Ruby 2.7.x - too old
|
|
904
|
+
assert!(!make_config("2", "7", "-1").has_ruby_dln_check_abi());
|
|
905
|
+
}
|
|
906
|
+
}
|