Nixのstore path計算方法メモ

Nixでは、パッケージの再現性を担保するために、/nix/store/下にハッシュ値を含んだ名前であらゆるファイルを保管する。そのハッシュ値がどのような情報から計算されるものなのかを知っておくことは、なぜNixが再現性を確保できるのかを考える上で重要である。 そこで、この記事では、Nixのstore path、つまりその中に含まれるハッシュの計算方法について解説し、実際にステップバイステップで計算してみる。 参考記事 How Nix Isntantiation Works (Web Archive) Nix manual(unstable)Store Pathの仕様 Nix PillsのChapter 18 なお、本記事では nix derivation show コマンドの結果からいろいろと情報を取り出すために jq を用いる。 store pathの種類 ほとんどStore Pathの書き起こしみたいになってしまうが書いておく。 まずstore pathは、/nix/store/<digest>-<name>の形式を持っている。 <digest>というのは、fingerprint(後述)をSHA256でハッシュ化し、160bitに圧縮したうえでNix32表現にしたもの。ドキュメントには「SHA256の先頭160bitをBase32表現にしたもの」と記載があるが、 Base32という言葉はRelease Note 2.20でNix32という名前に改められた。理由としては通常の意味のBase32表現とは処理が異なり紛らわしいためのようだ 先頭160bitを単純に切り取ってNix32表現にするのではなく、実装では complressHash という関数で圧縮処理が行われている(該当ソース)。 fingerprintは、<type>:sha256:<inner-digest>:/nix/store:<name>の形式 <type>というのは以下のいずれか text:<input store path>:<input store path>:...:derivation。<input store path>には、(存在すれば)derivationが参照する他のファイルのパスを指定する source:<input store path>:<input store path>:...:外部から持ってきたファイルをNAR形式でアーカイブ化したもの sourceがinput store pathを持つケースってどんなときなの?と感じるが、確かにlibstore/store-api.ccにそれっぽいコードが見つかる。しかし実例がまだ良くわかっていない…。 output:<id>:derivationからビルドされたもの、もしくはビルド予定のものを表す。<id>には通常outが入るが、ビルド出力結果を複数分けているようなパッケージではbinやlib、devなどが指定されうる。 <inner-digest>は、inner-fingerprintをSHA256でハッシュ化し、Base16表現にしたもの inner-fingerprintの計算方法は、上述のtypeによって異なるが、これは後々実際に計算してみつつ解説する いろいろと書いてあるが、結局/nix/store下におかれるパスの種類は実質fingerprintの種類であり、すなわち3種類である。 text:derivationを表す source:ビルドに必要なファイル、ソースコードを表す output:ビルド生成物そのもの、ないしディレクトリを表す (前準備)derivationの準備 今回手で計算するもととなるderivationを簡単に書く。 Nix PillsのChapter 7の内容をもとに。汎用性とかは意識せず、x86_64-linux前提で書く ただNix Pillsをそのまま書き起こしになってしまうのもつまらないので、flakeを使って書いてみる。 まずいくつかのファイルを作成する flake.nix:flakeファイル default.nix で分けないで、ここに直接derivationを書く mubuilder....

2024-04-20 · (updated 2024-04-21) · 7 min · 1462 words