もしあなたがこのような素晴らしいCargo.toml
を書いたとしよう。
[package]
name = "your-brilliant-app"
edition = "2024"
version = "1.0.0-alpha"
description = "A brilliant app that does something amazing."
authors = ["John Doe <john.doe@example.com>"]
license = "MIT OR Apache-2.0"
homepage = "https://example.com/your-brilliant-app"
しかし、これを配布する段になって、もう一度バージョンに説明、ライセンスにパッケージ名と入力するのは退屈だ。そこで、Nixを使ってCargo.toml
のような言語固有の設定ファイルとより一般的な形式のパッケージのメタデータを接続する。
本題
動機
Nixでは、(正確には、Nixpkgsは、) パッケージングの際に、パッケージを表現する辞書型のmeta
キーにメタデータを含めるような仕組みになっている。例えば、slのメタデータは、
# Copyright (c) 2003-2025 Eelco Dolstra and the Nixpkgs/NixOS contributors
# Full license: https://github.com/NixOS/nixpkgs/blob/master/COPYING
# https://github.com/NixOS/nixpkgs/blob/master/pkgs/by-name/sl/sl/package.nix
stdenv.mkDerivation rec {
pname = "sl";
version = "5.05";
# 中略
meta = with lib; {
description = "Steam Locomotive runs across your terminal when you type 'sl'";
homepage = "http://www.tkl.iis.u-tokyo.ac.jp/~toyoda/index_e.html";
license = rec {
shortName = "Toyoda Masashi's free software license";
fullName = shortName;
url = "https://github.com/eyJhb/sl/blob/master/LICENSE";
};
maintainers = with maintainers; [ eyjhb ];
platforms = platforms.unix;
mainProgram = "sl";
};
}
というように記述されている。Nixpkgsのようなソースコードを直接管理しないプロジェクトではメタデータをNix式にハードコードすることは自然かもしれないが、ソースコードの隣にあるflake.nix
でパッケージをNix経由で配布する際には、フレームワーク側の設定ファイルとNix式の両方に同じメタデータを置くのは美しくない。
実装
完全な実装は https://github.com/comavius/dont-repeat-your-version-tag を参照のこと。
まず、Cargo.tomlの内容をNix式の世界に持ち込む必要がある。
# type: string
cargo-toml-text = builtins.readFile ./Cargo.toml;
# type: attrset
cargo-toml-parsed = builtins.fromTOML cargo-toml-text;
# あるいは、
# type: attrset
cargo-toml = builtins.fromTOML (builtins.readFile ./Cargo.toml);
次に、stdenv.mkDerivation
のメタデータをcargo-toml
から設定する。
rustPlatform.buildRustPackage {
# `pname` and `version` are read from Cargo.toml.
pname = cargo-toml.package.name;
version = cargo-toml.package.version;
src = ./.;
cargoLock = {
lockFile = ./Cargo.lock;
};
# Also, metadata is read from Cargo.toml.
meta = with cargo-toml.package; {
inherit description homepage;
license.spdxId = license;
};
};
実装が終わったので、実際にメタデータが正しく設定されているか確認する。
まずはstore pathから。
$ nix eval
«derivation /nix/store/bnjp5y0bdrrrg56w93nhlayrl3x1yq13-dry_metadata-1.0.0-alpha.drv»
Cargo.toml
に書かれたとおり、パッケージ名はdry_metadata
、バージョンは1.0.0-alpha
となっている。
次はmeta
を確認する。
$ nix eval ".#default.meta" --json | jq '.license'
{
"spdxId": "CC-BY-SA-4.0"
}
こちらも確かに、Cargo.toml
と同じ値が設定されている。
課題
本稿ではSPDX License Identifierを挟むことでCargo.toml
のライセンス表記をNixの習慣に沿った形で渡すことができたが、Cargo.toml
にはフィールドがないもののNixでは習慣的に使われているライセンスへのリンクを設定することができなかった。SPDX Licence Listにあるライセンスの場合何らかの方法でIDからその他の情報への変換ができると思うので、機会があれば挑戦したい。
終わりに
このように、Nixを使うことで開発者体験を高めることができる。そんなNixのインストールはこちらから: