GNU Guixのパッケージモジュール作成について

# GNU Guixのパッケージモジュール作成について

## はじめに

- [処理系固有のツールを避けたい＆Guixインストール](https://qiita.com/NOEU/items/f7958daad2edfc851a78)
- [GNU GuixでQuicklispから卒業したい](https://qiita.com/NOEU/items/600393dad7f5e76f7052)

の続きです。
チャネル作成時、前回の投稿ではGITリポジトリにpushしないと動作を確認できませんでした。前回の投稿＋αの情報を付け加えつつ、ローカルでチャネルの登録・動作確認を行う方法をまとめます。パッケージ定義自体の作成方法、チャネル登録方法は[前回の投稿](https://qiita.com/NOEU/items/600393dad7f5e76f7052)を参照してください。

## Guixのパッケージモジュールの定義

GNU Guixのデフォルトチャネルでは、`gnu packages xxxxx`というパッケージモジュール（名前空間）で各種パッケージが定義されています。この実体は、Guixパッケージのリポジトリ (https://git.savannah.gnu.org/git/guix.git) をCloneしてくることで実際に確認できます。例えば、Common Lisp関連のパッケージは、Cloneしてきたリポジトリのデータ内の、`gnu/packages/lisp-xyz.scm`というファイルで定義されています。

`lisp-xyz.scm`の一番最初のコードを見ると、次のようにdefine-moduleというオペレーターが使用されています。

```scheme:lisp-xyz.scm
(define-module (gnu packages lisp-xyz)
;; 省略
)
```

ディレクトリとモジュール名は対応しており、例えば`hoge/piyo/fuga.scm`という位置にファイルがある場合は、`(define-module (hoge piyo fuga) ...)`という形で記述します。

Guixは、デフォルトで`gnu packages`以下の全てのモジュールを読み込むようになっています。そのため、もし自分独自のパッケージモジュールを読み込む場合は、前回の投稿のように`channels.scm`に登録するか、それ以外にもいくつかの方法が用意されています。

## channels.scmでローカルにあるパッケージ定義ファイルを参照

次のように`file://`を使い、リポジトリURLを参照したときと同じような形で(ブランチの指定は省きますが）パスを指定できます。

```scheme:~/.config/guix/channels.scm
(cons (channel
       (name 'cl-guix)
       (url "file:///home/username/guix-packages"))
      %default-channels)
```

このようにパスを指定した場合で例えば、(noeu packages common-lisp)というパッケージモジュールを独自に定義する際は、`~/guix-packages/noeu/packages/common-lisp.scm`というファイルを作成しておく形になります。

`channels.scm`を記述したら、通常どおり`guix pull`でチャネル登録情報を更新します。しかし、guix pullはあまり高速ではありません。すぐにパッケージモジュールを登録できる方法がふたつあります。

## 環境変数GUIX_PACKAGE_PATHによる登録

GUIX_PACKAGE_PATHという環境変数にパッケージモジュールのあるディレクトリまでのパスを指定することで登録できます。`noeu`からはじまるディレクトリがパッケージモジュールの本体なので、`$HOME/guix-packages`までを指定することに注意します(scmまでのディレクトリパスは指定しない)。

```bash
$ export GUIX_PACKAGE_PATH=$HOME/guix-packages
```

## guix package -L による登録

次のように、`guix package -L`に登録したいパスを指定することでも対応できます。

```bash
$ guix package -L $HOME/guix-packages
```

## 登録後のパッケージ検索

次のようにパッケージ定義ファイル内にパッケージを定義しておき、`guix package -s package-name`で自分の定義したパッケージが検索結果にきちんと出てくるかを確認します。

環境変数、コマンドによるパッケージモジュールの登録は、`guix pull`を行わなくても、common-lisp.scmファイルの変更を即座に検出するため、動作確認がしやすくなります。

## guix build でパッケージの動作確認

実際に正常にパッケージをインストールできるかどうかを確認する場合は、`guix build [package-name]`で確認できます。例えばGITリポジトリURLに間違ったものを指定しており取得できない場合、`guix build`コマンドを使うと次のようにリポジトリのfetchエラーが発生することを手元で確認できます。

```bash
$ guix build my-cl-sdl2
...
Initialized empty Git repository in /gnu/store/9yh6pr445m70lgls9ql3zrnyfgvl37i3-cl-guix-sdl3-1.1.0-1.1588954-checkout/.git/
fatal: could not read Username for 'https://github.com': No such device or address
Failed to do a shallow fetch; retrying a full fetch...
fatal: could not read Username for 'https://github.com': No such device or address
git-fetch: '/gnu/store/zm51w1zv9zchx3n3xjw81zrjnlaswawa-git-minimal-2.25.1/bin/git fetch origin' failed with exit code 128
...
```

そのパッケージ定義が正常に動作する場合は、次のようなメッセージが最後に表示されます。

```bash
successfully built /gnu/store/arkzb2j9mc6qfzvxn12vpp7snb0p9zz5-cl-guix-sdl3-1.1.0-1.1588954.drv
/gnu/store/7036dy6bj6jg1z48pwam1ya61yvv36a8-cl-guix-sdl3-1.1.0-1.1588954
```

## 参考

・ [Guix Manual - Defining Packages](https://guix.gnu.org/manual/en/html_node/Defining-Packages.html)