長い間 cygwin 側の ruby のパッケージメンテナが不在だったが、EOL で放置されてしまっている状態は rubyist としては寂しいと感じ、一念発起して adopt *1 することした。*2
まず、先に rubygems を更新することにした。理由は以下の記事に書いてるとおり。
こちらはあっさりアップデートが完了できた。メンテナ向け ML でのやりとりは以下のとおり。
アップデートすることで自分の環境では不具合っぽい現象を踏んでしまったが、似たような issue が挙がっていたため、わかってることをコメントしておいた。*3
次に本丸の ruby の更新に着手した。ML でのやりとりは以下のとおり。
cygwin 側でメンテナンスしている ruby (と ruby で書かれたサブパッケージ群) は soversion によるパッケージ分け *4 をしていなかったため、何もせずに ruby-3.2.2 を current にすると、ruby-2.6.4 の cygruby260.dll
に依存しているものが軒並み動かなくなるということを教えてもらった。*5
対応策として perl でやっている依存管理の方法を教えてもらった。配布サーバの依存情報 setup.ini
*6 に provides
というヘッダがあり、そこに soversion 付きのラベル ruby_xy
(x
がメジャーバージョン、y
がマイナーバージョンになる。今回のアップデートで生成されるラベルは ruby_32
となる) を設定したら、それ以外の cygrubyxy0.dll
に依存しているものは新たにインストールできなくなるため、それを適用するということになった。
本当は他にも
- ruby-2.6.4 に
ruby_PROVIDES
を追加して再パッケージする。 - ruby に依存したパッケージの
depends
(上述のprovides
に対応するヘッダ) にruby_xy
を追加する。
など、手順がたくさんあるなあと思っていたが、メンテナのリードの方が直接 setup.ini
を書き換えるという強権発動? で、半分以上の作業は対応不要になった。
ということで ruby-3.2.2 のリリース以外にやるべきことは cygport の修正だけとなった。ちなみに cygport の修正は ruby-3.2.2 のリリース後に ruby に依存したパッケージを再ビルドに着手するまでに対応すれば良かったが、patch を書きたかったら書いてもいいよみたいなことを言われた & perl でやっている処理と同じようにすれば良さそうだったため、サラッと書いてみた。
これらの修正は ruby に依存したパッケージのビルド時にどの ruby の soversion に依存しているかを検出する処理であり、概要は以下のとおり。
vendor_ruby
配下に${major_version}.${minor_version}
というディレクトリがつくられるため、そこからruby_xy
をつくる。- バイナリの objdump の結果から
cygrubyxy0.dll
が見つかったら、そこからruby_xy
をつくる。 *7
これが merge されて cygport-0.36.3 がリリースされた。
そして ruby-3.2.2 のリリースをしようと、ジョブサーバからデプロイをすると、setup.ini
を再生成するスクリプトが実行されるのだが、しばらくするとエラーになってしまう。*8
ERROR: package 'ruby-caca' version '0.99.beta19-4' depends: 'ruby_23', but nothing satisfies that (以下略)
古い ruby に依存しているものに ruby-2.3.x が必要であるというラベル ruby_23
を setup.ini
にリードの方が付与していたが、既に ruby-2.3.x をインストールする方法がないため、依存解決ができないから setup.ini
を更新できない & ruby-3.2.2 のデプロイもされないという状態になった。
この状況を ML で質問すると、再びリードの方が対応してくれた。ドキュメントには明言されていないが、対応前後の setup.ini
の差分を見ると、depends2
ヘッダに ruby_23
が移動していたため、おそらくこのヘッダが「依存はあるけど無視しても良い」というものなのだろう。
というわけで何とかリリースをしたが、ちょっとしてやらかしが発覚してしまう。
gem install
して ~/bin
にインストールされたラッパースクリプト内の ruby
のパスが間違ってて、動かないという問題。
冷や汗を流しながら、必死に調べると、原因は以前からあるパッチ 2.0.0-cygwin-configure.patch
の適用を忘れていて *9、それによって rbconfig の中身が異なってしまっているせいだった。
詳細を説明すると LIBRUBY_RELATIVE
が true の場合は生成したラッパースクリプトと同じディレクトリに ruby
インタプリタがあるというラッパースクリプトを生成してしまう。false の場合は /usr/bin/ruby
になり、きちんと動く。
というわけでそれを適用して、再度リリースした。
再リリースしてからは追加の問い合わせメールは流れていないが、使用者があまりいないからなのかは正直わからない。*10
これから ruby_26
に依存しているパッケージの adopt をちょっとずつしていこうかと思っているが、個人的には gem は別に cygwin 側から提供しなくても、各自で gem install
すればいいんじゃないかという気がする。一人の人間がそれら全部を最新に追従させるのは困難、というかフルタイムコミットでも無理なのでは? と密かに思ってる。
*1:どうも cygwin ではメンテナ不在のパッケージのメンテナンスを引き受けることを adopt と表現するらしい。一般的にそういうのかはわからない。 https://cygwin.com/acronyms/#ITA
*2:読み間違える人はいないと思いますが念のために言っておくと ruby のコミッタになったわけではないです。
*3:一つ前の 3.0.4 では発生していなかったため、発見時はパッケージスクリプトのミスかわからなくて、かなり焦った。
*4:cygwin 側で配布している python はパッケージ名の末尾に soversion 由来の数字をつけることで別のパッケージとして、個別にインストールできるようにしている。他のディストリビューションでは FreeBSD がこの方式を採用している。 FreeBSD Ports Search
*5:インストールはできるけど、実行時に DLL が見つからないというエラーになる。例 : windows - dll file missing when debugging for android in Qt - Stack Overflow
*7:リリース後に気づいたが、これだと ruby 自身も ruby への依存を持ってしまうため、厳密には自身を除外する if 文が必要と思われる。あとで修正依頼を出す予定。
*8:非同期に実行するため、エラーはメールで届く。
*9:作業初期にそのままだと適用できないからとあとでやろうと外してしまっていたことを完全に忘れていた
*10:ダウンロード数を知る方法がないというのもある。