Ruby 3.2に同梱されるBundlerでは、 bundle gem
に --ext=rust
とすることでrustでgemのコードを書けるようになります。
新しいものはとりあえず触ってみたいので、試してみましょう(完全にn番煎じなのですが、自分用の備忘録です)
事前準備
- rustのビルド環境
- Ruby 3.2.0(正確にはBubdler 2.4.0以上)
やってみる
rust_gem_sample
という名前のライブラリを作ってみるとしましょう。
$ bundle gem rust_gem_sample --ext=rust : # 場合によってはさまざまな質問があるので適当に答える
これで雛形ができる。
作成された rust_gem_sample
ディレクトリへ移動し、コードをさらっと眺めてみましょう。
rustのコードはC言語の場合と同じように ext ディレクトリ内に生成される。
$ tree ext ext └── rust_gem_sample ├── Cargo.toml ├── extconf.rb └── src └── lib.rs
ちなみに、生成されるサンプルコードはこんな感じ
# ext/rust_gem_sample/src/lib.rs use magnus::{define_module, function, prelude::*, Error}; fn hello(subject: String) -> String { format!("Hello from Rust, {}!", subject) } #[magnus::init] fn init() -> Result<(), Error> { let module = define_module("RustGemSample")?; module.define_singleton_method("hello", function!(hello, 1))?; Ok(()) }
define_singleton_method
でメソッドが定義されているということは、RustGemSample.hello
で呼び出せて、1つの引数を受け取るコードってことですね。
さて、ビルドするためには事前準備が必要なので、以下を修正します(これはrust関係なく、bundle gemした時に必要な一般的なもの)。
rust_gem_sample.gemspec
- TODOをURLっぽい値に書き換えておく(これをしないとビルド時にエラーになる)
- testを生成している場合、自動生成された test コード
- デフォルトのコードは失敗するようなコードになっているので、修正するなり消すなりする必要がある
これは余談ですが、久しぶりにgemspecの中身を見て source_code_uri
や changelog_uri
というのが設定できるということを知りました。RubyGemsのドキュメントを見るに、設定しておくとrubygems.orgのサイドバーにいい感じに表示してくれるっぽいですね……?
$ ./bin/setup
$ bundle exec rake
これで無事にビルドできるはずです。
ではお試しで実行してみましょう。
$ ./bin/console Ignoring rust_gem_sample-0.1.0 because its extensions are not built. Try: gem pristine rust_gem_sample --version 0.1.0 irb(main):001:0> RustGemSample.hello("hoge") => "Hello from Rust, hoge!" irb(main):002:0>
おー、うごいた!
せっかくなのでブログにしてみよーと思って書き始めたのですが、なんか、思ったより何もせず動いてしまった……(いい話)。