ライブラリサーチパスの取得 - nmosh / Racket / Gauche / chibi-scheme / Sagittarius

DLLのソースコード生成は完成してGitHubにpushしたが特に書くことが無かった。。
というわけで淡々と続きを作っていく。今回はライブラリサーチパスの取得。

どこにDLLを配置するか問題

そろそろyuniFFIについてもテスト環境を構築する必要が有る。yuniFFIがサポートしようとしているScheme処理系は:

今はゲーム開発の方が忙しい状況で、手元のマシンを全部Windows/Macにしている。というわけでLinux/BSDVMでしかテストできないので優先度が下がり気味という状況にある。
というわけで、開発効率を意識しつつ以下のようなルールを決めた:

  • Windows上ではテストツリーと開発ツリーを分離しない。VisualStudio等で直接デバッグするため。
    • つまり、Win32 / Win64 / Cygwin32 / Cygwin64で同一ツリーにDLLを配置できる必要がある。他の環境は後で考える。
  • Windows / MacOS / Linux / FreeBSDではツリーを混ぜない。
    • ABIを混ぜないので、全部の拡張子を順に試すように実装できる
    • 例えばLinuxの.soとFreeBSDの.soが単一ツリーで同居できる必要は無い。DLLのbasenameをOS毎に変更する必要が無い

yuniのツリーを`run/buildstub.sh`でビルドすると、ディレクトリ`lib-stub`が生成され、各種Scheme処理系に合わせたライブラリwrapperが生成される。このlib-stubをDLLの配置場所に流用し、以下のように配置することにする。

lib-stub/
 + yunistub-win32/yunistub_SDL2.dll
 + yunistub-win64/yunistub_SDL2.dll
 + yunistub-cygwin32/cygyunistub_SDL2.dll
 + yunistub-cygwin64/cygyunistub_SDL2.dll
 + yunistub/libyunistub_SDL2.so
 + yunistub/libyunistub_SDL2.dyld

つまりWindowsだけABI固有ディレクトリを持ち、それ以外のOSでは、単にlib-stub/yunistubを使用する。
Scheme側のライブラリは"yunistub_SDL2"という名前でこれらのDLLなりsoなりdyldにアクセスするが、ランタイムライブラリがプレフィックスやライブラリパスを補って総当たりで検索することになる。

各種Scheme処理系でのライブラリパスの取得

大抵のScheme処理系では、ライブラリパスをコマンドラインによって指定することができる。yuniのリポジトリには、サポートしている処理系向けに、リポジトリ内のライブラリをライブラリパスに含めて処理系を起動するためのスクリプトが色々揃えてある( https://github.com/okuoku/yuni/tree/master/run )。
しかし、このライブラリパスを取得するための方法は処理系によってマチマチなので、compatレイヤとして処理系毎に実装してやる必要がある。

nmoshはグローバル変数`prefix-list`にライブラリパスを格納しているので、それをprimitives構文でインポートしてやればアクセスできる。
... ちゃんとAPIにした方が良さそうだ。

Racketは、(racket base)ライブラリにあるcurrent-library-collection-pathsパラメタで取得することができるが、取得できるのはpathオブジェクトのimmutableなpairでできたlistであるため、mapとpath→string手続きで変換してやる必要がある。
... そして、R6RSのmapはmutableなpairでできたlistのmapであるため、Racketのmapを明示的にimportしてきて使用する必要がある。

Gaucheグローバル変数*load-path*にライブラリパスを格納している。というわけで、専用のGaucheモジュールを用意し、それをR7RSライブラリにimportしてアクセスする。
(gauche base)あたりのモジュールでエクスポートされていると思いきや存在しないようだ。

ドキュメントされていないパラメタcurrent-module-pathでライブラリパスにアクセスできる。

Sagittariusは組込み手続きのload-pathでライブラリパスにアクセスできる。

次の一手

というわけで、Windows上でyuniをサポートしている処理系全てでライブラリパスにアクセスできるようになった。
次の一手は、適当なランタイムライブラリを用意し、各種処理系で定数テーブルの取得を行えるようにする。最終的なランタイムライブラリでは、S式を使ってクールにC APIが呼び出せるようにしたいが、そこまで辿り付くのはまだまだ距離が有る。