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

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 についてはオプションが存在しないっぽい

ということで手詰まり終了。

Rubyのプロジェクトの雛形 + gemの生成/公開にjewelerを使うようにしてみた

世界的にはマイナーでしたが、個人的には cutagem が大好きでした。

gemを作るとき、プロジェクトを作るときには結局何を使うと嬉しいのだろう

ですが cutagem は明らかに gemcutter.org というか rubygems.org 時代に対応する感じがなさそうです。そこでもう一度試してみました。

で、結果、jeweler にしてみました。

technicalpickles's jeweler at master - GitHub

試したもの

ruby-toolbox.com の上位3つ。

  • jeweler
  • bones
  • newgem

だけ。

簡単な感想

jeweler
予想以上に多機能。テストツールやドキュメンテーションツールなどを雛形作成時に選べるので、rdoc + test/unit なプロジェクトも yard + rspec なプロジェクトも作れる。個人的には徐々に移行しようかと思っているのでこういうのは助かる。ただし、git + github + gemcutter.org に完全に依存していて、新しいプロジェクトを作るといきなり git init & commit までいってしまう。(rubyforge に上げることもできる。)
bones
Rakefile の中身がスカスカなのが気になる。きっと gem library の中にいろいろ記述されているんだろうけど、ちょっとここだけ修正したい、などには対応できなくなってしまう。また、テストは rspec しか考えてないっぽい。
newgem
Rails 寄りすぎて個人的にはあまり活用シーンがなさそう。

github-username をセットしておらず、jeweler でちょっとハマる

1年前の2009年10月には

InfoQ: RubyForgeは徐々に廃止され、RubyGems.orgがGemホスティングを引き継ぐ

ということで rubyforge.org は廃止の方向で話が進み始めています。他のコードホスティングサービス、github や google code の方が優れている機能を rubygems.org にわざわざ移植することはしないそうです。

その中で jeweler は git & github を標準としました。これを表すものとして

  • github の username を要求し、
  • いきなり git commit してしまう

という潔さに自分は感動しました。ただし一つハマったことがあって、それは

github の username が必要

な点。これには

  1. jeweler –github-username USERNAME で指定する
  2. ~/.gitconfig の github.user で指定する

の2つの方法があります。2 は

[github]
        username = USERNAME

という記述のことで、これは

git config --global github.user USERNAME

で指定することと一緒です。

もう2年以上 github を使っていながら github 用の設定を .gitconfig に用意していなかったので新しいプロジェクトを作ることができなくてしばらく悩んでしまいました。(というか、一回 jeweler に挫折しました。ちゃんとエラーメッセージ読んでなかった。)

でももう大丈夫。この間

crontabwrap | RubyGems.org | your community gem host

をリリースしてだいぶ感じをつかんだので、今後はこれでいこうかなと考えています。

[2010-10-09 追記]

https://rubygems.org/ にパッケージを上げると http://rubydoc.info/ に自動的にドキュメントが生成されるみたい。これはすごいなぁ。

Fastladder の bot の If-Modified-Since が変

Last-Modified を勉強して意気揚々としていたところ、更新されてもいない item が Fastladder でどうしても更新として現れてしまうという現象に気づきました。

以前、生成済みの静的な feed ファイルについては公開時に checksum なりダイジェストで確認して行うといいというような話を書きましたが、今回の feed は動的に生成し、request header に応じて redirect させるとか 304 Not Modified を返すとか、細かい制御を行いたいと考えていました。この現象は要するに 304 が返ってないんだなーと思い、とりあえず bot についてはいくつかヘッダの情報をログに落として確認してみました。

そこで発見。

Fastladder FeedFetcher/0.01 という bot はサーバの response した Last-Modified ではなく、最新 item の pubDate(last modified) の日時を If-Modified-Since で送ってきている。

それはどうなんだ。

そんなにいくつも調べてはいないのですが、少なくとも FeedBurner についてはサーバの返した Last-Modified をそのまま送ってよこします1。今回吐いていた feed は最新 item の日時と実際に feed を生成する時刻がずれており、つまり最新 item の日時と Last-Modified が合わないのは仕様です。ということは

Fastladder bot には必ず 200 が返ってしまう

のです。

やっぱ変だよなぁ、これ。と思って調べてみたところ、こんな記述を見つけました。

To get best results when sending an If-Modified-Since header field for cache validation, clients are advised to use the exact date string received in a previous Last-Modified header field whenever possible.

cf. RFC 2616 - Hypertext Transfer Protocol – HTTP/1.1

「ベストな結果を得るには、キャッシュの検証のために If-Modified-Since ヘッダを送る際には、クライアントは可能な限り前回リクエストで受け取った Last-Modified の文字列を正確に利用することが推奨される。」

わけですよ! やっぱそうだよね! なんで FeedFetcher は最新 item のタイムスタンプなんすか! Last-Modified を使ってくださいよ!

しかしじゃあなんで静的ファイルの場合は最新 item の時刻と食い違ってても更新として出てこないのかな? まだなんか秘密があるのかなぁ?

[追記] はてブに的確なツッコミ降臨。

kazuhooku 「推奨」であって義務じゃないよ。それに、RSSファイルが更新されたかというのと、フィードのアイテムの更新判定はまた別の話

いやまぁそうなんですけどね。もう一度整理すると疑問は2つあって、

  1. あえて違う値を使う意味あんのかなー?
    • 例えば Last-Modified が返ってこない場合とかなら分かります。まーでもだったら If-Modified-Since にそれ付けてもたぶん意味ないよなーと思いますけど。
  2. なぜ今回の feed だけ更新判定ミスってるのかな?2
    • これはこちらでもっと追求しないといけないと思います。

ということなんですよね。もしかして吐いてる HTTP date がまだ何かおかしいのかしら?(これがいちばんかっこ悪いパターン。)

個人的には今回の件以外にも更新判定ミスっててちょっと困ってる feed があるのですが、これも合わせて調べてみた方がいいかな。これは自分で提供してるものではないので、外から分かる範囲になっちゃうけど。

[2008-10-16 追記]

その後、誤検出については内容を増やした辺りからなくなったように思う。

んだけど、なんか今日気づいたけど If-Modified-Since に Last-Modified から 35分弱早い謎の時間を送ってくるようになっていた。これは予想していなかった。なんだろう、この微妙にずれた時間は。

  1. 最初実は間違えて JST な Last-Modified を返していたのですが、そのときも真面目に GMT なスタンプで送ってきてました。実は HTTP date の仕様に気づいたのはこれがきっかけでした。 

  2. 特定の item でも最新の item もないけどなんか法則性ありますね。うーん? 

Reminderfox + iCal も難しい

メールドリブンのイベント、タスクについては Reminderfox が便利そうという話は以前からしているんだけど、これのアラーム通知や iCal アプリとしての使い勝手はイマイチなので、これと iCal を組み合わせようと思ったのだけれど、結論から言うとこれは無理。1

iCal 1.5.5 ではカレンダーを PUT するか GET するか最初に決め打たないといけない。日本語に言い直すと公開用のカレンダーと表示用のカレンダーである。

今回は Reminderfox からスタートするので表示用のカレンダーになってしまうが、そうなると iCal 上で細かく時間の調整やアラームの設定をやり直すことはできなくなる。転記して別なカレンダー上でアラーム設定することはできるが、それって無駄くさくね?

逆に公開用のカレンダーにすると問答無用でローカルの情報をサーバ上に PUT してしまうので、別なアプリで書き換えた情報はあっけなく消えてしまう。

ぬー。iCal 2 + iSync なら問題ないのかもしれないけど、そういう選択肢はないしなぁ。


ちなみに Reminderfox 1.5 からカレンダーを WebDAV でエクスポートする際は認証がなくてもユーザー名が必要な様子。ただ、それが分かっててもなぜか予期せぬエラーが頻発するので、WebDAV での保存周りなどはまだ十分なテストが行われていないのでしょうな。

また、iCal 1.5.5 のアラーム機能はやはり予想通りなかなかよかった。iCal のアラームウィンドウは問答無用で最前面に出続けるが、他のアプリで普通に作業できるし、iCal は alarm 用の daemon を持っているので、iCal 自体を立ち上げておく必要はない。これなら Growl とかなくたって十分実用的だ。

惜しい!

あ。Sunbird は読み書きできるな。Sunbird で編集して iCal で通知? 違うな、Sunbird が Growl に対応してればいいのか。それか iCal データパースして自力で growlnotify に投げる? さすがにそこまでやる気はないなぁ。

  1. Reminderfox 1.5 + iCal 1.5.5 だから? 

fc2 が画像の直リンを弾いてるっぽい

お気に入りのねこブログがしばらく前(2週間くらい前かな?)から bloglines では何が何やら分からなくなってしまった。HTML の方では正しくねこを拝むことができるので、たぶん feed 経由の「いわゆる直リン」を弾くように設定が変わっちゃったんだろな。しかしねこ写真のブログなのに写真見れないんじゃ意味ないからなぁ。こういうのは feed に直接画像を埋め込んじゃう1とかすれば回避できるんだろか。

この話に限らず、少し前から写真熱を取り戻そうとか思いながらスナップ写真を載せてるブログの feed をいくつか見てるんだけど、写真が入っていない feed の多いこと多いこと。photolog なのに画像が入ってないんじゃまったく意味ないじゃんとか思うんだが、やはりまだそういう人たちにはそれほど feed はアピールできてないのかな。あるいはどうしても HTML の方を見てほしい理由があるのか。2

どうしても HTML にアクセスしてほしい(例えば写真の見やすさを考慮した背景などのデザインに凝っている)場合は、フィードにちょっと画質を落としたサムネイルを含め、「もっと読む」なんかで HTML の方へ誘導する方法もあるような気がするんだけど、どうだろう。

もっとアグレッシブに写真の一部にモザイクが掛かっている feed だとさらに HTML への誘導効果は高いかな。あ、そういう「CM またぎ feed 生成サービス」みたいなのあったら面白いかも。画像の一部にモザイクが掛かるとか、固有名詞っぽいところが勝手に伏せ字になるとか、人物を差してそうだったら「ある大物SE」とかイニシャルに差し変わっちゃうの。3「もっと読む」のリンクの方は一回広告を表示してから HTML が出力される仕組みになってるの。

どうよ。放送業界に学ぶ feed 広告ビジネス。

  1. base64 とかで 

  2. たぶん存在そのもののや利用方法がよく分かっていないっていうのがいちばん正しい現状認識だろうけど。 

  3. 大物 SE ってなんだ? 

ビスが…

おれはハードには興味ない人間だからそんなもの回せませんorz 精密ドライバーが限界です。

買ってこなきゃ。あーめんどくせ。次はやっぱ ThinkPad に戻そうかな。

参考 みんなもできる!PowerBook G4/12"簡単バラし

目標達成率 38.9%

うーん。

また ssh つつき

なんか毎日どこからか来てるのね。今日はドイツ、この間は中国。中国はトータルすると多いな。香港、台湾もあるな。フィリピンの gov.ph なんてのもきてるんだが、おいおい、いいのか?

なんかどうも知らなかっただけで(ぉぃ)日常茶飯事らしいので、気にしないこととする。

それって後だしジャンケンじゃ。。。

@IT:初級システム管理者のためのセキュリティ入門「にわか管理者奮闘記」補遺編2

実はポリシーありました、実は手順書ありました、ってそれどうですか。ああた。

うーん。なんだろうなぁ、初期の頃はエキセントリックというか、読み物的な面白さを求めすぎたと言うか。。。たぶんネットワークセキュリティで考えられる要素を欲張って詰め込んだ結果、内容が追いついて来れなかったという感じなのかなぁと思っている。事件 → ツールの紹介 → とにかく頑張って解決、というプロセスが短すぎて、管理者はみんなスーパーマンか、おい、という具合。

ツールの使いこなしもやたらと早いしね。いくらなんだって新人くんがネットワーク構成図がないことにいち早く気づいたり、次々とサーバ向け、管理向けのツールが使いこなせるとか、どうかなと思う。紹介されている学生時代のパソコンの使い方と違いすぎる。なんか、ちょっとパソコンに強いくらいでも頑張ればすぐ管理者に慣れますよ的な間違った印象を与えてないかーって気がする。まぁそんな人は @IT のこの連載読んでないと思うけど。

というわけで今度始まるらしい新・中村くんは期待してますよ!

MVP Awards

なんか Microsoft から表彰されている人が。

[MVP] 更新〜今年も一年宜しくお願いします〜<MVP と MS の皆様

なんだろうと思ったら

MVP Awards

こんなものがあるんだな。すごいですね。「活躍」ってのはこういうのを言うんだな。

目標達成率 29%

いよいよやばいですな

About

例によって個人のなんちゃらです

Recent Posts

Categories

Tool 日々 Web Biz Net Apple MS ことば News Unix howto Food PHP Movie Edu Community Book Security Text TV Perl Ruby Music Pdoc 生き方 RDoc ViewCVS CVS Rsync Disk Mail FreeBSD Cygwin PDF Photo Zebedee Debian OSX Comic Cron Sysadmin Font Analog iCal Sunbird DNS Linux Wiki Emacs Thunderbird Sitecopy Terminal Drawing tDiary AppleScript Life Money Omni PukiWiki Xen XREA Zsh Screen CASL Firefox Fink zsh haXe Ecmascript PATH_INFO SQLite PEAR Lighttpd FastCGI Subversion au prototype.js jsUnit Apache Trac Template Java Rhino Mochikit Feed Bloglines CSS del.icio.us SBS qwikWeb gettext Ajax JSDoc Rails HTML CHM EPWING NDTP EB IE CLI ck ThinkPad Toy WSH RFC readline rlwrap ImageMagick epeg Frenzy sysprep Ubuntu MeCab DTP ERD DBMS eclipse Eclipse Awk RD Diigo XAMPP RubyGems PHPDoc iCab DOM YAML Camino Geekmonkey w3m Scheme Gauche Lisp JSAN Google VMware DSL SLAX Safari Markdown Textile IRC Jabber Fastladder MacPorts LLSpirit CPAN Mozilla Twitter OpenFL Rswatch ITS NTP GUI Pragger Yapra XML Mobile Git Study JSON VirtualBox Samba Pear Growl Mercurial Rack Capistrano Rake Win RSS Mechanize Sitemaps Android JavaScript Python RTM OOo iPod Yahoo Unicode Github iTunes God SBM friendfeed Friendfeed HokuUn Sinatra TDD Test Project Evernote iPad Geohash Location Map Search Simplenote Image WebKit RSpec Phone CSV WiMAX USB Chrome RubyKaigi RubyKaigi2011 Space CoffeeScript Nokogiri Hpricot Rubygems jQuery Node GTD CI UX Design VCS Kanazawa.rb Kindle Amazon Agile Vagrant Chef Windows Composer Dotenv PaaS Itamae SaaS Docker Swagger Grape WebAPI Microservices OmniAuth HTTP 分析基盤 CDN Terraform IaaS HCL Webpack Vue.js BigQuery Middleman CMS AWS PNG Laravel Selenium OAuth OpenAPI GitHub UML GCP TypeScript SQL Hanami Document SVG AsciiDoc Pandoc DocBook Develop Jekyll macOS Node.js Vite Heroku Transformer AI Data Cloud Wasm