2019/12/06

ziprubyapp: 実行可能なRubyスクリプトアーカイバ

妙なもの第2弾。

ziprubyapp: Make an executable ruby script bundle using zip archive

コンピュータとだけマルチリンガルな私としては、Python と Perl と Ruby と OCaml は同じくらいの頻度で話したり(実際の所、Perlはここ20年でぐっと減りました)するのですが、
PythonPerl でできるなら、Ruby でもやりたい、単一ファイル実行形式でお手軽自作ツール運用したいと思うのは自然な流れなので。

こちらも結果としては、単一ディレクトリに依存ファイル (*.rb だけですが) を置いて ziprubyapp で処理すると、サクッと1ファイルの実行スクリプトにまとめてそれらしく実行してくれます。




実のところ、Python と Perl とは異なり、Ruby では読み込み機構辺りはベースの C 言語でガッツリ実装されてしまっていて、あまり手が出せないのです。RubyGems では require 機構を拡張していますが、これはメソッドの直接置換えで乗っ取っている上に、最終的にはシステム上に存在するファイルに $LOAD_PATH を通して従前の require に処理移譲するようになっています。
テンポラリディレクトリに吐き出して実行するような方法もありますが、smart ではないですよね。

といいつつ色々調べているうちに、eval と TOPLEVEL_BINDING を使えば大体同じようなことは実現できることが分かってきたので、Ruby版に移植しました。
 内部的な話としては、要はモジュールのソースを eval(source, TOPLEVEL_BINDING) すれば、細かいところは置いておいて、大体 load と同じ処理になるようです。自作の suid_sudo 位なら問題なく動いてくれます。

String IO 経由で言語本体の use/require にモジュールを渡せるPerlとは異なり、Ruby のこちらの方法ではシステム側の require/load を全く使わないので、多重読み込みの排除とか、同時読み込みの排他制御とか自分でやらなければならないこともあり、その辺りは RubyGems の require とかを部分的に参考にしました。

Ruby の require まわり、Python並とは言わずとも、Perl並に require/load が拡張できると、便利なんですけどね。

0 件のコメント: