Nix flakes で OCaml project を管理する
背景
先日、NixOS を導入し、dotfiles を一通りアップデートしました。
(記事はないので適当に https://github.com/lmdexpr/dotfiles を見てください)
準備ができたぞ、というところで、いざ OCaml を書こうとしてみると、うまく動かせない。
例えばopam switch
で環境作ろうとすると ld がなく、コンパイラを入れることも出来ない。
そっちはそっちで解決策もあるようですが、折角なら Nix flakes を用いてプロジェクトごとに環境を再現できるようにしてしまおうと思いました。
その記録です。
Nix flakes とは
Nixはパッケージマネージャです。
その記述に使うのは Nix 言語という独自の関数型言語です。非常に簡単です。
システム自体の記述も行えますし、そこに乗っかった Linux distribution が NixOS です。
一方でFlakesは Nix 上の実験的機能になります。
flake
を扱うための機能です。
flake
と呼ばれるものは、flake.nix
をルートに持つ file system tree (git や tarball も含みます) のことです。
それを管理するということはつまり、ビルド方法を指定したり、その過程で必要な依存関係を指定したりすることが出来るということです。
うーん、便利。
なくなったらどうしよう。[1]
Nix flakes を使うためには
まず Nix をインストールします。
その上で有効化する必要があります。
詳細は公式に任せますので、上記リンクから探してください。(投げやり)
OCaml の普通の開発環境について
前提として OCaml を普通に開発する方法について整理しておきます。
まずパッケージマネージャーとして opam が存在します。
hoge.opam
に hoge というプロジェクトについて記述することが出来ます。
前述のようにopam switch
というコマンドがあり、これによってディレクトリごとの環境を立てられるのですが NixOS とはどうも相性が悪く……。
次にデファクトスタンダードなビルドシステムとして dune が存在します。
Jane Street という OCaml を使っている企業として有名なところが OSS として出しているものです。
設定の記述が S 式になっていて、扱いやすいです。
*.opam
を生成することも出来ます。
OCaml のプロジェクトを作成したくなったら、
-
opam
をインストール -
opam install dune
でdune
をインストール -
dune-project
ファイルを記述しdune build
する(ここで*.opam
も生成出来る)
という形で組み立てていました。
ところで、これは僕が知らないだけでどうにか出来るかもしれませんが opam -> dune -> opam みたいな依存になっているのヤバくないですか?
OCaml の開発環境を Nix flakes で組み立てる
本題です。
ここで「*.opam
という元々ある設定を活用したい」です。
どうするかというと https://github.com/tweag/opam-nix という便利なテンプレートがあるので使います。
終わりです。(え?)
README にもありますが https://www.tweag.io/blog/2023-02-16-opam-nix/ というブログポストに詳細な使い方もあります。
これをなぞるだけで本当に一瞬で環境が作れてしまいます。
Nix サイコー。
本当にブログポストの内容が全てなので語ることは特にないのですが、それではアレなので自分が必要だと思った部分だけ抜き出しておきます。
-
*.opam
を準備する -
nix flake init -t github:tweag/opam-nix
で出来たflake.nix
を修正 -
git add .
(nix は git にトラックされているかとかを見てたりします(一敗)) nix develop
これで完璧です。
Dune を使う
上記のブログポストにもありますがdune-project
を使うことも出来ます。
つまり、最早opam
を(明示的に)使うこともなくなりました。
ほんまか。
その場合 1. で準備した*.opam
の代わりにdune-project
を配置し、2.のテンプレート修正時にbuildOpamProject
をbuildDuneProject
に変えれば良いです。
便利~。
Direnv を使う
開発の度にnix develop
するのはダルすぎます。
なので nix 的によく使われているらしい Direnv を使います。[2]
プロジェクトルートでdirenv edit .
して、中にuse flake
とだけ書いておくとcd
するだけで諸々の環境がセットアップされます。
最高すぎ。
他の言語のプロジェクトで使う
まだ経験がありませんが、同様のテンプレートや仕組みは他の言語でも当然あります。
なので同様にすればいけると思いますし、なくても自分で作ればいいんじゃないかな。(適当)
おわり
Nix サイコー
Discussion