Skip to content

Commit 6ab2129

Browse files
committed
fix: check stable API rust impl file exists at build time
When detecting Ruby versions like 3.5 (ruby-head), the build would fail with a missing file error because is_stable() only checked version ranges rather than verifying a corresponding ruby_X_Y.rs file exists. Replace is_stable() with has_rust_impl() that checks for actual file existence. This allows ruby-head or other versions without impls to correctly fall back to compiled C when stable-api-compiled-fallback is enabled, or error clearly when it's not.
1 parent c087445 commit 6ab2129

File tree

4 files changed

+26
-14
lines changed

4 files changed

+26
-14
lines changed

Gemfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ gem "racc"
1313
gem "base64"
1414
gem "yard"
1515
gem "mutex_m"
16-
gem "standard"
16+
gem "standard", "~> 1.52.0"
1717
gem "tsort"
1818

1919
gem "ostruct", "~> 0.6.3"

crates/rb-sys/build/stable_api_config.rs

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,23 @@ use crate::{
66
};
77
use std::{convert::TryFrom, error::Error, path::Path};
88

9+
/// Check if a Rust implementation file exists for the given Ruby version.
10+
fn has_rust_impl(version: Version) -> bool {
11+
let crate_dir = Path::new(env!("CARGO_MANIFEST_DIR"));
12+
let path = crate_dir.join("src").join("stable_api").join(format!(
13+
"ruby_{}_{}.rs",
14+
version.major(),
15+
version.minor()
16+
));
17+
18+
let exists = path.exists();
19+
20+
// Ensure we rebuild if the file is added or removed
21+
println!("cargo:rerun-if-changed={}", path.display());
22+
23+
exists
24+
}
25+
926
pub fn setup(rb_config: &RbConfig) -> Result<(), Box<dyn Error>> {
1027
let ruby_version = Version::current(rb_config);
1128
let ruby_engine = rb_config.ruby_engine();
@@ -42,7 +59,7 @@ impl TryFrom<(RubyEngine, Version)> for Strategy {
4259
RubyEngine::Mri => {}
4360
}
4461

45-
if current_ruby_version.is_stable() {
62+
if has_rust_impl(current_ruby_version) {
4663
strategy = Some(Strategy::RustOnly(current_ruby_version));
4764
} else {
4865
maybe_warn_old_ruby_version(current_ruby_version);
@@ -76,10 +93,10 @@ impl Strategy {
7693
println!("cargo:rustc-check-cfg=cfg(stable_api_has_rust_impl)");
7794
match self {
7895
Strategy::RustOnly(current_ruby_version) => {
79-
if current_ruby_version.is_stable() {
96+
if has_rust_impl(current_ruby_version) {
8097
println!("cargo:rustc-cfg=stable_api_include_rust_impl");
8198
} else {
82-
return Err(format!("A stable Ruby API is needed but could not find a candidate. If you are using a stable version of Ruby, try upgrading rb-sys. Otherwise if you are testing against ruby-head or Ruby < {}, enable the `stable-api-compiled-fallback` feature in rb-sys.", MIN_SUPPORTED_STABLE_VERSION).into());
99+
return Err(format!("No Rust stable API implementation found for Ruby {}. If you are using a stable version of Ruby, try upgrading rb-sys. Otherwise if you are testing against ruby-head or Ruby < {}, enable the `stable-api-compiled-fallback` feature in rb-sys.", current_ruby_version, MIN_SUPPORTED_STABLE_VERSION).into());
83100
}
84101
}
85102
Strategy::CompiledOnly => {
@@ -88,7 +105,7 @@ impl Strategy {
88105
println!("cargo:rustc-cfg=stable_api_export_compiled_as_api");
89106
}
90107
Strategy::RustThenCompiled(current_ruby_version) => {
91-
if current_ruby_version.is_stable() {
108+
if has_rust_impl(current_ruby_version) {
92109
println!("cargo:rustc-cfg=stable_api_has_rust_impl");
93110
println!("cargo:rustc-cfg=stable_api_include_rust_impl");
94111
} else {
@@ -102,7 +119,7 @@ impl Strategy {
102119

103120
println!("cargo:rustc-cfg=stable_api_enable_compiled_mod");
104121

105-
if current_ruby_version.is_stable() {
122+
if has_rust_impl(current_ruby_version) {
106123
println!("cargo:rustc-cfg=stable_api_include_rust_impl");
107124
} else {
108125
println!("cargo:rustc-cfg=stable_api_export_compiled_as_api");

crates/rb-sys/build/version.rs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,6 @@ impl Version {
3636
}
3737
}
3838
}
39-
40-
#[allow(dead_code)]
41-
pub fn is_stable(&self) -> bool {
42-
*self >= MIN_SUPPORTED_STABLE_VERSION && *self <= LATEST_STABLE_VERSION
43-
}
4439
}
4540

4641
impl std::fmt::Display for Version {

script/show-asm

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -585,9 +585,9 @@ class ShowAsm
585585
archhdrdir = ruby_config["rubyarchhdrdir"]
586586

587587
cmd = [cc, src_file.path,
588-
"-S", # Output assembly
589-
"-O3", # Optimize
590-
"-fno-stack-protector", # Disable stack canary for fair comparison
588+
"-S", # Output assembly
589+
"-O3", # Optimize
590+
"-fno-stack-protector", # Disable stack canary for fair comparison
591591
"-I#{hdrdir}",
592592
"-I#{archhdrdir}",
593593
"-o", asm_file.path]

0 commit comments

Comments
 (0)