先日までRustでRubyのネイティブ拡張をビルドする方法を調べていたのだけど、やっと ruby gems として公開するところまでもっていけた。
調子にのってかなり大胆な名前を付けてしまった。

hello_rust_gem

RubyGems: https://rubygems.org/gems/hello_rust
GitHub: https://github.com/irxground/hello_rust_gem
(コードレビューしていただけると大変助かります!!)

このgem自体は意味がなく、RustでRubyのgemを書きたいときの参考にできることを目的として作成した。
hello_rust_gemは他のライブラリに一切依存していない。(ただし、rspecのような開発時に利用するライブラリは除く)

使い方

require "hello_rust"

p HelloRust::VERSION

各ファイルの説明

src/lib.rs

このファイルはRubyのネイティブ拡張の本体部分になる。
中身は HelloRust モジュールおよび HelloRust::VERSION 定数の定義のみなので、大したことはしていない。
本物のネイティブ拡張を書くときはここを拡張していけばよい。

Cargo.toml

Rustプロジェクトの定義。重要なのは crate-type = [“cdylib”] の部分のみ

build.rs

RustのコードからRuby APIをリンクするための設定を生成している。 build.rs は cargo build するときに自動的に呼ばれる。

lib/hello_rust.rb

これは外から require “hello_rust” したときに読み込まれるファイルになる。
いきなりネイティブライブラリを読み込むようにすると、いざRubyコードが書きたくなった時に困るかもしれないので最初の入り口はRubyファイルにしておくとよい。というより、 bundle gem –ext がそうなのでそれに則った。

中で require “hello_rust/hello_rust” しているが、この部分でネイティブライブラリを読み込んでいる。

hello_rust.gemspec

RubyGems の設定を書くファイル。今回は例として、Cargo.toml に書かれたデータを再利用してみたが、そうする必要はない。(が、バージョン番号の更新はミスしやすいのでこの例のように一か所にまとめた方が良いかもしれない)

重要なのは spec.extensions = [“ext/Rakefile”] の部分で、
gem install するとソースコードを配置した後、ネイティブ拡張をビルドするために ext/Rakefile が実行される。

Rakefile

開発者が使う rake コマンドのための Rakefile
rake で成果物を消して、ビルドして、テストを実行する。
rake fmt でRustとRubyのフォーマッターが走る。
その他については rake -T を参照。

ext/Rakefile

gemspecに書いた通り、 gem install の際に呼ばれる。
RUBYLIBDIR という環境変数が渡されるのでそこにネイティブライブラリを配置する。
今回は require “hello_rust/hello_rust” で読み込めるように、ファイルパスは $RUBYLIBDIR/hello_rust/hello_rust.so に(Linuxの場合)なる。

ext/build_task.rb

ローカル開発するときとgemをインストールするときは、どちらもコンパイルして適切なパスにライブラリを配置することになるので、共通する部分をここにまとめた。

Windowsでビルドするときには、RUSTUP_TOOLCHAIN 環境変数を設定している。
RubyInstaller で入るRubyはmingwだが、WindowsでのRustはmingwとmsvcの二種類から選べるので、mingwを強制するため。

それ以外

あとはテストやライセンスファイル等。
spec/hello_rust_spec.rb は HelloRust::VERSION をテストしており、最小限だがネイティブライブラリのコンパイルに失敗すると気づけるテストにはなっている。

今後

だいたいのプラットフォームで動くことは確認できたので、CIを充実させていきたい。

广告
将在 10 秒后关闭
bannerAds