Rubyを評価するCLIツールはCRubyとmrubyのどちらで実装するべきか

  • 22
    いいね
  • 0
    コメント

最近MItamaexkremapなど、Rubyで設定ファイルを既述するCLIツールをCRubyではなくmrubyで実装することがあったのだが、そのようなCLIツールを作る際にCRubyではなくmrubyを使うことへの妥当性について考えていたことをダンプしておく。

以下、ハードウェアにmrubyを組み込む用途や、Ruby以外で書かれた既存のツールにmrubyを組み込む用途については(僕は特に経験してないので)除外して書きます。

CLIツールの作成にmrubyを使うメリット

  • CRubyやrubygemsの存在に依存しないバイナリとしてCLIツールを作ることができる
    • gem installする場合に比べ、rbenvに気を使わずバイナリを叩くだけで手軽に実行できる
      • gem installして入れたCLIツールは、rbenvが入っている環境ではrbenv globalや.ruby-versionが違ったりsudoでユーザーが変わると動かなかったりするので、rbenvに気を使って実行しないといけない
    • Ruby以外の依存も解決できれば、ダウンロードするだけで実行可能なバイナリにでき、配布が楽になる
      • CRubyで作ったツールは、CRubyが既に入った環境でgem installさせるか、chef/omnibusなどを使って各OS/ディストリビューションごとにCRubyごとパッケージングする必要がある

CLIツールの作成にmrubyを使うデメリット

  • CLI関係なくmrubyを使う際のデメリットがある
    • 実装する時に一部の標準ライブラリやrubygemsが使えないので、自分で移植する必要がある
      • デフォルトでは require がないし、ほぼ確実にそのままでは動かない
        • mruby-requireを使うと、実行時にそのRubyのファイルが必要になってしまうので、mrubyが何らかのハードウェア/ソフトウェアに組み込む用途に使われる以上、極力使わない方が良い
      • 移植しても、本家に変更を追従させるのが大変
      • 移植する時にCのコードを書く機会が多い
        • 特に、CLIツールで使いそうなmruby-ioに必要なメソッドが足りなかったりする
      • RSpecが使えない
      • pryが使えない
    • mrubyはRubyの言語機能が一部実装されていない
      • キーワード引数とかない
    • CRubyに比べるとmrubyやサードパーティmrbgemの安定性が低い
      • CRubyだとcoreに入っているような機能もmrubyだとサードパーティなので信頼性は低い
      • undefined methodの時にたまにSEGVするが再現が困難で報告しにくい
      • mruby-threadを使うとmruby-ioとかが壊れる
  • mruby-cliを使っていても、Cのライブラリに依存したmrbgemを追加するとリンクやクロスコンパイル環境の準備が面倒
    • 例えばmruby-cli上でmruby-onig-regexpのWindows向けのクロスコンパイルがうまくいかない

Rubyのスクリプトを評価するCLIツールはどんな時にmrubyで実装するべきなのか

これまでの話を総合すると、「mrubyを使ってCLIツールを実装すると、mrubyのエコシステムの成熟度的にメンテが大変になる代わりに、ツールを実行するまでのコストを下げることができる」という話になる。デメリットに上げた部分は がんばれば どれも解決可能な点が重要で、ツールを実装する時にがんばるのと、CLIツールを配布・実行する時にがんばるのとどちらが大変かで決めればよさそう。

で、技術選定の基準となりそうな事象のそれぞれにかかるコストを比べ、僕はmrubyで作るかどうかを以下のような基準で考えている。


例えば開発環境をMItamaeでセットアップする場合、まっさらなマシンでもセットアップしたいので「実行環境にCRubyを要求できる」が「いいえ」、僕の会社での用途だとhomebrew自体のセットアップもMItamaeのレシピでやっているので「パッケージングした方が実行が楽」が「いいえ」となり「mrubyで実装」になる。
xkremapの場合、僕のデスクトップマシンにはCRubyが入っているので「実行環境にCRubyを要求できる」は「はい」、実行するためにいちいちGemfileとか置きたくないので「Bundler管理下での実行を想定」が「いいえ」、僕のマシンにはrbenvが入っていて、rbenvで管理している特定のバージョンでxkremapが常に入っているようにしたりrbenvのコマンドを叩いて起動するのが面倒だし、かといってsystem rubyを使うとインストールに無駄にsudoが必要になるし、かつxkremapの実装コストのボトルネックになるXlibプログラミングではRubyのバインディングが用意されていてもさほど助からない(Cでの例やドキュメントが多いので、Cで書いた方が楽)のと、僕が既にMItamaeでmrubyに慣れているので、「mrubyで実装するよりrbenvについて考える方が面倒」が「はい」となり「mrubyで実装」になる。

まあrbenvについては大分細かい話な気もするが、rubygemでインストールしたツールの実行時にrbenvに悩まされたことがある人は普通にいるんじゃないだろうか。

お気持ち

mrubyがもっと便利になれば、どんなCLIツールもmrubyで実装した方が手軽で便利、という日も来るかもしれない。

CRubyを使うかどうか迷わせるほどmrubyやそのエコシステムを便利にしてくださっているみなさま、いつもありがとうございます。