GNU Guixで依存関係を考慮したCommon Lisp用のパッケージ定義

# GNU Guixで依存関係を考慮したCommon Lisp用のパッケージ定義

## はじめに

(QiitaでGNU Guix関連の投稿が他に一切ないことに気づいた今日この頃)。続きものなのか若干怪しいですが、以下の投稿の続きです。

- [処理系固有のツールを避けたい＆Guixインストール](https://qiita.com/NOEU/items/f7958daad2edfc851a78)
- [GNU GuixでQuicklispから卒業したい](https://qiita.com/NOEU/items/600393dad7f5e76f7052)
- [GNU Guixのパッケージモジュール作成について](https://qiita.com/NOEU/items/0307f09670f8dc94c030)

前回パッケージモジュールの作成方法についてメモしましたが、「[GNU GuixでQuicklispから卒業したい](https://qiita.com/NOEU/items/600393dad7f5e76f7052)」の投稿内容だけだとCommon Lispのパッケージ定義を行う上で依存関係を解決することができず、不十分な内容でした。今回はその辺りの内容が解決したのでまとめます。

また、SDL2、GSLL、GETTEXTなど、GNU Guix標準パッケージに含まれていないいくつかのCommon Lispのパッケージを含むチャネル用リポジトリを作りました。次のリポジトリになります。

https://gitlab.com/hu.moonstone/guix-channel.git

.config/guix/channels.scmでチャネルに登録するか、GUIX_PACKAGE_PATH環境変数に登録し、

```bash
$ guix package -i cl-sdl2
```

とすることで簡単にインストールできるようになります。

## Common Lisp用パッケージの定義

Guix本体の`gnu/packages/lisp-xyz.scm`で定義方法を確認できます。ここでは、`lisp-xyz.scm`に含まれていない`cl-sdl2`をどのように定義するかを見ていきます。

最初に、こちらで作成したパッケージ定義のコードを以下に記載します。

```scheme:
(define-public sbcl-cl-sdl2
  (let ((revision "1")
        (commit "1588954ee4abc37b01a7e2e17a76e84fd4da8c77"))
    (package
     (name "sbcl-cl-sdl2")
     (version (git-version "1.0.0" revision commit))
     (source
      (origin
       (method git-fetch)
       (uri (git-reference
             (url "https://github.com/lispgames/cl-sdl2.git")
             (commit commit)))
       (file-name (git-file-name name version))
       (sha256
        (base32 "15x5d139qj3zba2qx3r43s1sh2bqgm4zcwd07kx2l23q2j89v509"))))
     (inputs `(("autowrap" ,sbcl-cl-autowrap)
               ("alexandria" ,sbcl-alexandria)
               ("cl-ppcre" ,sbcl-cl-ppcre)
               ("trivial-features", sbcl-trivial-features)
               ("trivial-channels", sbcl-trivial-channels)))
     (build-system asdf-build-system/sbcl)
     (synopsis "sdl2")
     (description "")
     (home-page "https://github.com/lispgames/cl-sdl2")
     (license license:expat))))

(define-public cl-sdl2
  (sbcl-package->cl-source-package sbcl-cl-sdl2))

(define-public ecl-cl-sdl2
  (sbcl-package->ecl-package sbcl-cl-sdl2))
```

gitリポジトリから取得する記述等は、[GNU GuixでQuicklispから卒業したい](https://qiita.com/NOEU/items/600393dad7f5e76f7052)で投稿しているので省きますが、`sbcl-`、`ecl-`、`cl-`という接頭辞のついた3つのパッケージを定義していることが重要です。

最初、コンパイル済みバイナリは不要と考えていたため、`sbcl-`、`ecl-`のパッケージを作成せず、`cl-`のみで、`build-system asdf-build-system/souce`を使ってソースのみをインストールするようパッケージを定義していましたが、その場合依存するパッケージが同時にインストールされません。

この問題をGuixコミュニティに質問したところ、修正すべき問題かもしれないという感じになってますが、今動かしたいので現在の作法にのっとって、sbclを軸にしたパッケージ定義を作成する必要があります。

先程のパッケージ定義のコードは、`sbcl-cl-sdl2`を定義し、その上で`cl-sdl2`はソースのインストール、`ecl-cl-sdl2`はECL用コンパイル済みバイナリのインストールという定義になっています。ECL向けはオプションですが、`sbcl-`の定義は必須となります。

## 自分専用のチャンネルを作る意味

Common Lispの書くこと自体まだ怪しい感じですが、Common Lisp向けのパッケージをECLで動作させようとする場合、少しの修正で動作するもののメンテナーさんがいるのかよくわからない感じのプロジェクトもあります。科学計算を行うGNU Scientific LibraryのCommon Lisp用パッケージGSLLも、関連するAntikパッケージの問題により現在そのままでは動作しません。

Antik本家には、CLISP向けとECL向けのマージリクエストがあるものの、取り込まれていないので、それを取り込んだ上でディスパッチマクロでエラーが出る部分を修正したものを、https://gitlab.com/hu.moonstone/antik にで管理するようにしました(ECLの開発者の人に言われた通りに修正しただけな感じなのでまだ問題が出るかもしれませんが……)。その上で、自分のGuixチャネルにパッケージを登録しています。

GNU Guixを使えば自分の修正を加えたパッケージを管理し、簡単にインストールできるようになります。

## 終わりに

という感じで、依存パッケージの自動インストールにかなり手こずった感じだったんですが、lisp-xyz.scmの通りにするとうまくいき、Quicklispから脱却し、完全にGNU GuixでCommon Lispパッケージの管理を行うことができるようになりました。

GNU Guixデフォルトのチャネルは、Quicklispに登録されているパッケージ数と比較して限られたものですが、今後も必要に応じてパッケージ定義を追加していく形にしたいと思ってます。GNU Guixを使っている人は少ないのかな……と思ったりもしてますが、書き方がわかればdebパッケージやrpmパッケージを作るより簡単で、Quicklispより柔軟性があると思うのでおすすめです。

## 参考

- [GNU Guix Reference Manual](https://guix.gnu.org/manual/en/guix.html)