Nixとは何か
「Nixとは何か?」という質問に答えるのは大変です。
まずは公式の説明をみてみましょう。
Nix, the purely functional package manager
Nixは純粋関数型パッケージマネージャであると説明されています。この意味を理解するにはまず、パッケージマネージャがどういったソフトウェアなのかを明らかにする必要があります。
現代の開発では当たり前のツールになっているため忘れがちですが、パッケージマネージャは複雑なソフトウェアです。Nixについて学ぶ前に前提知識を整理しましょう。
パッケージマネージャとは?
Debianの定義を引用します。
A package manager keeps track of what software is installed on your computer, and allows you to easily install new software, upgrade software to newer versions, or remove software that you previously installed.
What is a package manager?
パッケージマネージャとは、コンピュータにインストールされているソフトウェアを管理し、ソフトウェアを簡単に追加/更新/削除できるようにするツールだと述べられています。
しれっと出てきましたが「インストール」とは何でしょうか。
ダウンロードとの違いを考えます。ダウンロードはインターネット上のリソースをローカルのコンピュータに取り込むことです。一方、インストールは、ダウンロードしたリソースをローカルのコンピュータの適切な場所に配置し、必要な設定を行い、そのリソースを使えるようにすることです。
パッケージとは?
パッケージマネージャは、ソフトウェアを「パッケージ」単位で管理します。パッケージの中身には以下のようなものが含まれます。
- 実行可能ファイル
- 共有ライブラリ
- 静的アセット(テキスト、音声、フォント、etc...)
パッケージマネージャを経由してソフトウェアをインストールした場合、パッケージマネージャはパッケージに含まれるファイルを自動的に適切な場所に配置します。例えば一般的なUNIX系システムでは、実行可能ファイルは/usr/bin
、共有ライブラリは/usr/lib
、静的アセットは/usr/share
などに配置されます。こうして実行可能ファイルはPATH環境変数を経由してシェルからコマンドとして実行できるようになり、共有ライブラリは動的リンカからロードできるようになります。
対してプログラミング言語のパッケージマネージャの場合、パッケージは専用のディレクトリで一元管理されることが多いです。
パッケージマネージャの定義
現代のパッケージマネージャは過去のものと比べるとかなり多機能です。例えばNode.jsのnpmはnpmパッケージを管理するだけでなく、lockファイルによる依存関係の固定やスクリプト実行を行うことができます。RustのCargoは依存関係の固定はもちろん、プロジェクトのビルドやテスト、ドキュメント生成が可能です。一方、PythonのpipはnpmやCargoと比べるとそこまで機能は多くありません。このようにパッケージマネージャと一口に言っても機能が大きく異なる場合があります。
なので、今後の議論を円滑にするために、ここで本書における「パッケージマネージャ」を定義しておきます。
- パッケージリポジトリからパッケージをダウンロードする
- パッケージの依存関係を自動的に解決する
- ビルドシステムを持つ
- パッケージのインストールを自動的に行う
以上の機能を持つものを「パッケージマネージャ」とします。
パッケージリポジトリから該当のパッケージ及び依存関係を自動的に取得し、パッケージ定義に従ってビルドした後、ユーザーの環境にソフトウェア本体や設定ファイルを自動的に配置する、というのが一連の動作です。
ビルドシステムについて、Debianのaptのようにローカルでビルドせず既にビルド済みのものをインストールするパッケージマネージャもありますが、それについては考えないことにします。
Nixは何が違うのか?
Nixは他のパッケージマネージャには見られない非常にユニークな仕組みを持っています。特に本書では以下の機能について解説します。
- 純粋関数的ビルドシステム
- Nixストアによるパッケージと依存関係の厳密な管理
- Nix言語とFlakesによる宣言的ビルド
- Profilesによる非破壊的パッケージ構成管理
いきなり固有名詞がたくさん出てきましたが順次解説していくので安心してください。