-
Notifications
You must be signed in to change notification settings - Fork 0
plans stale 01 native extension setup
STALE — fully executed. Matches ext/duckling/ and Rakefile on main. Kept for
historical record — see Stale Plans — Fully Executed (0.2.0 Shipped) and the roadmap
for the live 0.2.x plan.
Wire the native extension using Magnus 0.9 + rb-sys stable-api-compiled-fallback,
mirroring the canonical rust_blank example from the Magnus repo. The extension
crate lives at ext/duckling/ as a cdylib that depends on the
duckling rlib via a crates.io dependency. No build.rs is added to
the extension crate; Magnus's own build.rs propagates rb_sys_env::activate()
transitively.
-
cdylib + no build.rs: The verified
rust_blankexample contains nobuild.rsat the extension level. Magnus'sbuild.rscallsrb_sys_env::activate()and Cargo propagates link metadata up to the final cdylib. (Extension Crate Layout) -
stable-api-compiled-fallback: Pre-compiled stable ABI bindings; no bindgen or libclang required at build time. Taken directly from the rust_blank
Cargo.toml. (Extension Crate Layout) -
extconf.rb pattern:
create_rust_makefile("duckling/duckling")is the complete 3-line pattern from the verified rust_blank example. (extconf.rb Pattern) -
Rake::ExtensionTask with lib_dir:
lib_dir = "lib/duckling"aligns the compiled artifact location with the extconf.rb path argument and the expectedrequire "duckling/duckling"call. (Rakefile Setup) -
CI Rust toolchain:
dtolnay/rust-toolchain@stableis the standard action. Magnus 0.9 requires rustc 1.85+ (edition 2024 stabilized there). (CI Configuration)
New file. This is the cdylib extension crate.
[package]
name = "duckling_ext"
version = "0.1.0"
edition = "2024"
[lib]
crate-type = ["cdylib"]
[dependencies]
magnus = { version = "0.9" }
duckling = "0.4" # crates.io: https://crates.io/crates/duckling
rb-sys = { version = "*", default-features = false, features = ["stable-api-compiled-fallback"] }Notes:
-
edition = "2024"requires rustc 1.85+; Magnus 0.9 already requires 1.85. -
duckling = "0.4"is the crates.io dep — no path dependency needed. - No
[build-dependencies]orbuild.rs; Magnus handles rb_sys link metadata.
New file. Stub that compiles but registers nothing (bindings added in plan 02).
use magnus::{Error, Ruby};
#[magnus::init]
fn init(_ruby: &Ruby) -> Result<(), Error> {
Ok(())
}Currently empty (0 bytes). Replace with 3 lines:
require "mkmf"
require "rb_sys/mkmf"
create_rust_makefile("duckling/duckling")The argument "duckling/duckling" places the compiled artifact at
lib/duckling/duckling.bundle (macOS) or lib/duckling/duckling.so (Linux),
matching the lib_dir in step 4 and the require in step 5.
Add after existing requires, before the default task:
require "rake/extensiontask"
Rake::ExtensionTask.new("duckling") do |ext|
ext.lib_dir = "lib/duckling"
endUpdate the default task:
task default: %i[compile test standard]Rake executes prerequisites left-to-right, so compile runs before test.
Rake::ExtensionTask is provided by rake-compiler (~> 1.2.0), already a
development dependency in duckling.gemspec.
Add after the version require:
require_relative "duckling/duckling"This loads the compiled .bundle/.so produced by step 4.
Insert a Rust toolchain step between the Ruby setup step and the rake step:
- name: Set up Rust
uses: dtolnay/rust-toolchain@stableNo additional apt packages needed: stable-api-compiled-fallback uses
pre-compiled bindings, and duckling's dependencies (regex, chrono,
serde, serde_json, once_cell, smallvec) are pure Rust with no system library
requirements.
-
duckling not on crates.io.Resolved: The crate is published on crates.io asduckling = "0.4"(https://crates.io/crates/duckling). Useduckling = "0.4"in Cargo.toml — no path or git dependency needed. No crates.io blocker for RubyGems publication. (Extension Crate Layout) -
Resolved: the shippededition = "2024"and stable Rust.ext/duckling/Cargo.tomlactually usesedition = "2021"andmagnus = "0.8"(not"0.9"— Magnus 0.9 was never published to crates.io), sidestepping the 1.85+ requirement question entirely. CI is green onmainwith this setup. -
Resolved:actions/checkout@v6in existing CI.main's CI now pinsactions/checkouttov7.0.0by commit SHA (kept current bydependabot). See CI Configuration.
-
bundle exec rake compile— must succeed with no errors. -
ruby -e "require 'duckling'"— must not raiseLoadError. -
bundle exec rake test— existing version test must still pass. -
Confirm the compiled artifact exists:
ls lib/duckling/duckling.{bundle,so}— one of these must be present after compile.