Rubyスクリプトをcross-platformなstandaloneバイナリにしようとして諦めた
やりたいこと
- gem は自由に使いたい
- なんなら ffi も使いたい
- Ruby で書いて macOS / Windows で動作させたい
- Ruby そのもののインストールの手間を掛けさせたくない
きっかけは「GitHub Actions で Windows CI が使えるから、なんかいろいろゴニョゴニョすれば Windows で使う道具を作れるのでは?」
数年前に https://github.com/hone/mruby-cli も話題にあがったみたいなんだけど、確かに mruby 自体はプラットフォームを選ばないが gem 使いたいので除外した。
まとめ
Go をクロスプラットフォームで動く Ruby のように扱えないかなと思ったけど、やはりかなり厳しそうなので、2019年の今なら Ruby スクリプトをクロスプラットフォームで動かすなんてワケないのでは?と探したけど何度目かの挫折をして諦めた話。
- やはり Windows が鬼門
- 一時的に頑張る人が出てきても継続しない
もう Ruby のこの状況はずっと変わらないんだろうなぁ。個人的には型とか速度とかよりまず Windows で楽に動いてくれれば業務系の人ともっと仲良くしやすいんだけどなーと思ってるんだけど、もう諦めました。いい加減さすがに学べ、おれ。
※ Node.js でいってもいいんだけど、native extension とか ffi 周りは Ruby の方がだいぶマシだと思っている。
以下は戦いに破れた記録。
loureirorg/rb2exe: Ruby to EXE - Turn ruby scripts into portable executable apps
- 名前に反してクロスコンパイルもできるっぽいんだけど、
- Ruby が 2.2.2 固定のまま止まっている
これはさすがに放置だなぁということで捨て。
Enclose.IO: Compiling your application into a single executable
https://t.co/ZOFKojFv8c まさに自分のためのようなものが。
— wtnabe (@wtnabe) October 1, 2019
pmq20/ruby-packer: Packing your Ruby application into a single executable.
これは事前に実行環境込みの実行バイナリに固めてしまうので deploy や実行が速いといったメリットを掲げたプロジェクト。結構しっかりいろいろ作り込まれているが、配布自体は2年前に止まってしまっているように見える。
実際にやってみたが、
- squashfs を使っていて実行時にファイルから require のようなことを行わないっぽい
- コンパイルはすごく重い
- クロスコンパイルはできない
- 実行バイナリはそこそこの大きさで十分な速度で動く
- Mac については普段から rbenv を使っていることもあり、開発環境も整っているので簡単だったが、Linux は bison がないとか CPPFLAGS="-P" が足りなくて ncurses でコケる現象に悩んだ。あとなんかコンパイルは終わるのに途中途中で error が出ていて怖い。
- 予想通り Windows が厳しい
- Visual Studio を入れても nmake がないとか怒られる
- choco install で頑張る
- なんか Build Tools みたいなの入れたけど zlib.lib がないと怒られる(コンパイルのログには出てくるんだけど)
- これらを手作業じゃなくて「CI上で安定して動くようにする」のはだいぶつらそう
ということでこれで全部のプラットフォームを通すのは難しいと思って諦め。
mac で書いて Ruby 入っていない mac に持っていく分には時間さえ掛ければできそうなので、そういう用途に限ればよさそう。まぁいつまで使えるか分からないけど。
larsch/ocra: One-Click Ruby Application Builder
Windows は Windows 専用のやつの方がよいかもと思って試してみた。
- rubyc と違ってコンパイルは概ねガッチャンコするだけでめちゃくちゃ速い
- 逆に実行時には固めたものを展開して実行するようで、かなり遅い
- 単純なスクリプトだと ocra の実行もできあがったスクリプトの実行も簡単
- ただし実行時にそのまま require などが走るのでそこでファイルが見つからないと怒られる
- いろいろオプションがあって、何も指定しないと標準ライブラリすらバンドルされない
- 実行時エラーを潰して潰して頑張ったが openssl.so がないと怒られる
- どうも .rb や .dll はバンドルするオプションがあるのに .so についてはオプションが存在しないっぽい
ということで手詰まり終了。