というわけでDockerベースのテスト環境をTravisCIで始めた。基本的にはライブラリのbootstrapやFFIライブラリのビルドも含んだ完全なビルド過程の再現を含んでいる。もっとも、まだFFIテストは統合していない(まだ事故ったときにコアダンプとか回収できないし)。

Docker上でも"手元で成功するのにリモートで失敗するテスト" せっかくDockerにしたのに、一発目から"手元で成功するのにリモートで失敗するテスト"が表われてしまった。ある種の魔物がおるね。。 3/6 Test #3: RACKET-_sanity.sps ...............***Failed 0.78 sec lib-stub/racket/r7b-util/features.mzscheme.sls:6:4: import: cannot find suitable library installed (exception: collection-path: collection not found collection: "nmosh/r7rs" in collection directories: TravisCI上のDockerでは、なぜかRacketがnmosh用の互換ライブラリを見に行ってしまう。当然非Docker環境や手元のDocker(CentOS7上)ではずっとテストはパスしていた。これはDockerのストレージドライバの違いでファイルの列挙順が変わるというやつで、nmosh用のライブラリファイルである*.nmosh.slsをRacketの検索パスに入れてしまっていたため。

というわけでディレクトリを分離し、*.IMPLEMENTATION.slsのコンベンションをツリーでは使わないようにした。ついでにoverrideの順序も見直し。 https://github.com/okuoku/yuni/commit/bebd109057eab1f748496a0e698c909dd2fe137e これはかなり運の良いパターンで、偶然TravisCIと手元でストレージドライバが違っていなかったらこのバグも見つからなかった可能性が高い。環境を増やすのがいかに重要かというポイントでもある。

gauche-packageを呼ぶ Gauche版のyuniffi対応は専用モジュールが必要なので、ビルド時にgauche-packageを呼ぶように代えた。従来はgauche-packageが生成したファイルをコミットしていたが、gauche側のABIが変わったら終りなので。 https://github.com/okuoku/yuni/commit/cea4b08f75a5397f0748281a575ef59d65f094f7 ...冷静に考えるとこれgauche-packageでインストールまでやった方が良いんだろうか。。Docker環境ではrootなので問題なくinstallできるが、デフォルトのビルドがビルドツリーの外部に影響を与えるのはポリシに反するのでたぶんやらないけど。

ビルドには -I オプションを2つ渡す必要がある(yuniの共通ヘッダとGaucheモジュールの専用ヘッダ)が、gauche-packageが一つしか渡せないので--cppflagsと--cflagsに分けて与えている。基本的にGaucheがin-place build志向なので、CMakeのようなout-of-treeビルドを標準としたシステムとの食べ合せが悪い。

デフォルトのgauche-packageに.stubをビルドさせると適当な場所に.cを配置してしまうので、 ( use gauche.cgen.stub ) ( cgen-genstub "/path/to/repos/yuni/..../yuniffilib.stub" ) のようなSchemeソースをconfigure時に生成して呼ぶことにした。これを行うことで.cの生成場所を制御することができる。

Alpine Linux(Musl libc)対応 追記: ダメだった。Gaucheは動いたけどテストが失敗する。 https://github.com/okuoku/yunibase/issues/6

Docker用の小さなディストリビューションとして比較的人気のあるAlpine LinuxがMuslを採用しているのでテストとしてはこれを使っている。

なんと現状ビルドに成功しているのはchibi-schemeとchickenだけで、他は諸々の問題が有り上手くいっていない。

Gaucheは最近専用の対応がコミットされているので、backportして試すつもり。 https://github.com/shirok/Gauche/commit/13a196557848f22a1607a300643131345e9f32b3 基本的にglibc専用の機能はちゃんとチェックしてから使う必要があり、意外とLinuxのlibc == glibcという仮定を置いていることが多い。