2019-09-10

Saven: あなたの悩みを救うかもしれないビルドツール

Scheme にはSNOW!、Akku等のリポジトリ的がある。個人的にはこれらに乗っかってプログラムを組んだ方が楽だと思っているのではあるが、これらのリポジトリには登録されていないライブラリの依存関係を手作業でインストールするのは面倒。個人的によく使う r7rs-postgresql、r6rs-redis はどこのリポジトリにも入ってなかったりする。GitHub にコードがあるだけで、パッケージのパの字も考慮されていない(製作者の顔が見てみたいものだ)。リポジトリが使えれば楽だが、使えない状況である。となれば、今欲しいのはリポジトリではなくビルドツールではないだろうか?

ライブラリの依存関係は割と頭の痛い問題だ。例えば、r6rs-redis は r6rs-usocket に依存していて、r6rs-usocket は r6rs-pffi と r6rs-psystem に依存している。拙作の Pegasus はこの依存関係を考慮するように設計されているのだが、如何せんこれらのライブラリは Pegasus に登録されていない(製作者の以下略)。となると、手作業での依存関係解決が必要になる。作っているものが一つであればそれも問題ないのかもしれないが、複数になると一気にその手間は跳ね上がる。環境が変わればやり直しというのもジワジワと効いてくる。

Saven は依存関係を解消するビルドツールとして作られた。現状は GitHub 常にあるライブラリを解決できる。例えば、r6rs-mongodb と r6rs-pffi に依存するモジュール foo の定義はこんな感じで書ける
---
# sav.yaml
name: foo
dependencies:
  - type: github
    name: ktakashi/r6rs-mongodb
    paths:
      - src
  - type: github
    name: ktakashi/r6rs-pffi
    paths:
      - src
後は、sav buildsav test のように使える。複数ライブラリを構築したい場合にも使える。例えば、上記モジュール foo は親モジュール bar を持つとする。bar はこんな感じになる。
---
# sav.yaml
name: bar
modules:
  - foo
  - baz
さらに、モジュールの参照もこんな感じで可能
---
# sav.yaml
name: baz
dependencies:
  - type: module
    name: foo
    scope: test # Only used by tests

Saven を使えばビルド時、主にテスト時、に気になる依存関係を解決してくれる。まだまだ足りない機能の方が多いが、既にかなり楽ができるようになった。GitHub にしかないライブラリの依存を解決するのに、サブモジュール機能を使う必要がなくなったのは大きい。いつも通り欲しい機能順に実装されていく予定。

以下はどうでもいい話
Saven は Java の Maven にとてもインスパイアされている。
YAML 以外にも使えるフォーマットあるんだけど、なんとなく YAML が一番楽(今のところ)
Saven は英語の save がオランダ語化されたもので実際の単語だったりする。