目的
複数のレポジトリにあるプロジェクトを使って開発するときにgit submoduleを使うかと思います。
そのようなユースケースでnixとgit submoduleを組み合わせて使いたくなるかもしれません。
残念ながら、今の開発版のnix(2.6.0pre20211217_6e6e998)ではそのような使い方が難しいです。
なぜ難しいのか、今なら何ができるのか紹介します。
パッケージ作成:nix flakes
まず、nix & git submoduleでの使い方を紹介する前にnixでのパッケージの作り方としてのnix flakesについて簡単に説明します。
nixのパッケージはderivationですね。derivationはデフォルトのパッケージの集合であるnixpkgsから使用するパッケージや便利な関数、ビルドするソースとビルドするbashのスクリプトから構成されています。
nixpkgsはnixのスクリプトの中で<nixpkgs>
となっています。これはパッケージをビルドする時の環境変数NIX_PATH
が展開されます。
この環境変数はユーザーによって異なるため、そのまま使うと再現性のないパッケージが出来上がります。
それを防ぐためにnix flakesがあります。
nix flakesでは次のようなflake.nix
ファイルとそのロックファイルflake.lock
を使います。
見てわかる通りnixpkgsのパスが埋め込まれています。ロックファイルには具体的なgitのハッシュ値が書かれます。
今回の話はこのnix flakesとgit submoduleを一緒に使うのが難しいという話です。
# Source: https://www.tweag.io/blog/2020-05-25-flakes/
{
description = "A flake for building Hello World";
inputs.nixpkgs.url = github:NixOS/nixpkgs/nixos-20.03;
outputs = { self, nixpkgs }: {
defaultPackage.x86_64-linux =
# Notice the reference to nixpkgs here.
with import nixpkgs { system = "x86_64-linux"; };
stdenv.mkDerivation {
name = "hello";
src = self;
buildPhase = "gcc -o hello ./hello.c";
installPhase = "mkdir -p $out/bin; install -t $out/bin hello";
};
};
}
nixとgit submoduleの現状
nix flakesではbuiltins.fetchTree
関数でソースを取り込むのですが、デフォルトでgit submoduleを使わない設定になっていました。
そこで#4922のPRでデフォルトonにするように変更が加えられました。
しかし、パフォーマンスの問題があり、再びデフォルトoffに戻されています。(discourseのソース)
そのため、ユーザー定義によってgit submoduleを有効化する方法やデフォルトonにする方法が模索されています。
そのうち実行可能ものがsubmodules=1
というパラメータをあたえて有効化する方法です。#5434
これを使った方法を次に紹介します。
nixでgit submodulesを使う方法
nixでgit submodulesを使うためにflake.nix
を編集します。
nix flakesのinputsにsubmoduleへのパスを設定します。(この機能は#5279で実装されています。)
例えばmy-subdirディレクトリのsubmoduleをinputsにいれるには下記のようにします。
# Source: https://www.tweag.io/blog/2020-05-25-flakes/
{
description = "A flake for building Hello World";
inputs.nixpkgs.url = github:NixOS/nixpkgs/nixos-20.03;
inputs.my-submodule.url = path:./my-subdir; #ここに追加
outputs = { self, nixpkgs, my-submodule }: {
#あと省略
そのあとnixでgit submodulesは有効にするために.
を.?submodules=1
に書き換えて各種コマンドを実行します。
パッケージのリストを出す場合は次のようになります。
# git submoduleがない通常の場合
nix flake show .
# git submoduleがある場合
nix flake show .?submodules=1
また、パッケージの作成する場合は下記のようになります。
この例ではhelloパッケージ(derivation)を作成します。
# git submoduleがない通常の場合
nix build .#hello
# git submoduleがある場合
nix build .?submodules=1#hello
まとめ
nix flakesの簡単な紹介のあと、nixとgit submodulesを一緒に使うために、nix flakesでの設定方法と実行方法を紹介しました。