Mosh の Apple Silicon 対応 - 2022夏休み
scheme.org の方から mosh.scheme.org の利用について声をかけていただいた。せっかくなので Mosh の Apple Silicon 対応をしようと思いたった。なお最後のリリースは 0.2.7 で 2011/6/14 に okuoku さんによって行われている。10年以上前である。
C/C++ で書かれたソフトウェアなので新しいアーキテクチャ(=Apple Silicon)でちょいちょいとコンパイルし直せば良い。という話ではない。なぜならば Mosh のコンパイルには安定して動く Mosh が必要だから。これは gcc のビルドに gcc が必要なのと同じ問題で、bootstrap 問題と呼ばれる。さらにややこしいのが Mosh のコンパイラは Scheme で書かれており、これを VM で実行可能なコードにコンパイルするために Gauche で書かれた VM を使っていたりするので厄介である。
Step1: 0.2.7 リリースを雑にビルドする
まずは安定して動く Mosh のバイナリが欲しいのでリリースビルドをビルドする。リリースビルドのビルドには Mosh は必要ない。ビルドするとすぐに GC 周りのエラーになった。10年前の Boehm GC は Apple Silicon に対応していないので以下のエラーになる。
"The collector has not been ported to this machine/OS combination." # error "The collector has not been ported to this machine/OS combination." ^
そこでまず最新の Boehm GC を入手してビルドを試みる。10年の間に Boehm GC のディレクトリ構造などが変更になっており Mosh 側の Makefile に変更が必要である。行儀悪いが直接 Makefile を編集してことなきを得た。
続いて奇妙な以下のテストエラー。
(let ((b (make-bytevector 4 0))) (bytevector-sint-set! b 0 -1 'little 4) (bytevector-uint-ref b 0 'little 4)) : expected 4294967295 but got -1.
詳しく調べてみると Fixnum の 乗算内部で行われているオーバーフローチェックが意図通りうまく動いていないっぽい。
static Object mul(int n1, int n2) { const fixedint ret = (fixedint)n1 * n2; /* Overflow check from Gauche */ if ((n2 != 0 && ret / n2 != n1) || !Fixnum::canFit(ret)) { Return
const fixedint ret = (fixedint)n1 * n2;
この部分の fixedint は int の alias なのだが Apple のドキュメントによると乗算がオーバーフローしたときの動作は不定のようだ。なのでここは int よりも大きなサイズで判断しなければならず。const long ret = (fixedint)n1 * n2;
とするのが良さそう。
これを直してめでたく M1 上で動く Mosh がビルドできた。
Step2: macOS 上で bootstrap してみる
さて M1 mac 上で動く安定 Mosh バイナリができたので./gen-git-build.sh
を実行してみるがエラー。Scheme で書かれたコンパイラを gosh を利用して変換している処理。詳細を調べたり Gauche のバージョンを当時のものに合わせてみたがダメだった。不安定な土台な上で何かをやるのは筋が悪いと気づいた。
Step3: Ubuntu on Docker を試す
Linux 上で Mosh をビルドして動かす方が枯れていて良いだろうということで Docker で。i386 Ubuntu image ではうまくいかなかったので i686 Ubuntu image でやってみたら動いた。依存ライブラリの大半は apt install で取得できるのだが、正規表現ライブラリの oniguruma は特定のバージョンをソースコードからビルド。 ./gen-git-build.sh では autoconf も利用しているのだが正直なところエラーが出たとしても対処できそうにない。
無事 bootstrap できたので tar.gz にまとめてドキュメントを書き。 Release mosh-0.2.8-rc1 · higepon/mosh · GitHub にリリースしておいた。
所感
10年以上前に書かれたコードを新しいアーキテクチャで動かすのは思ったよりも面倒。記憶を頼りにいくつものツール・デバッグを繰り返してやりたいことができたが、最近ではそういう面倒にはほとんど遭遇しない。Tensorflow のバージョン違いで問題が起きるとか、cuda のインストールとか平和なものばかりである。懐かしい気持ちだが、ツールの試行錯誤より本質に時間を使える今の方が良いね。
詳細なログはNotes: Mosh 0.2.7 on M1 mac · Issue #14 · higepon/mosh · GitHubに。