あとで忘れると面倒くさそうなのでメモ。
話の前提
Nixを使ってCMakeを使ったプロジェクトをビルドしようとすると、時々 CPMFindPackage や FetchContent_Declare を使ったプロジェクトに出くわします。
CPMFindPackage や FetchContent_Declare はプロジェクトの configure 時にネットワークを利用するため、Nixのビルドシステムと相性が悪いのですが、とは言えこれをビルドするにはどうしたらいいんだ?というのが今回のメモです。
解決策
以下の二つをやる。
cmakeFlagsに-DCPM_USE_LOCAL_PACKAGES=YESと-DFETCHCONTENT_FULLY_DISCONNECTED=YESを指定するbuild/_deps/${name}-srcに依存するファイルを突っ込む
まず(1)について。
これは CPMFindPackage と FetchContent_Declare のネットワークアクセスを無効化するオプションで、この二つを指定することによって configurePhase でのネットワークアクセスを完全に遮断できます。
次に(2)についてですが、これは CPMFindPackage や FetchContent_Declare は依存の解決時に build/_deps/${name}-src を参照するため、ここにソースを突っ込めば万事解決、という訳です。
ちょっとした具体例
例えば nlohmann_json を CPMFindPackage で取得していた場合、まず fetchFromGitHub で適当な変数へソースファイルのパスを突っ込みます:
nlohmann_json = fetchFromGitHub {
owner = "nlohmann";
repo = "json";
rev = "230bfd15a2bb7f01ebb3fcd3cf898b697ef43c48";
hash = "sha256-baz2yhWPjz2anjOComV3ju3dG42bXxV9erWfj5WiSGw=";
};
次いで preConfigure フェーズへ下記のようなコードを仕込みます:
preConfigure = ''
mkdir -p build/_deps
cp -r --no-preserve=ownership,mode ${nlohmann_json} build/_deps/nlohmann_json-src
'';
最期にこれを使うCMakeプロジェクトをビルドすればOK、という事なります。
ただこの preConfigure の書き方は依存が大量にあると面倒なので、実際には下記のようなコードを利用しています:
preConfigure = let
deps = {
nlohmann_json = fetchFromGitHub {
owner = "nlohmann";
repo = "json";
rev = "230bfd15a2bb7f01ebb3fcd3cf898b697ef43c48";
hash = "sha256-baz2yhWPjz2anjOComV3ju3dG42bXxV9erWfj5WiSGw=";
};
};
in ''
mkdir -p build/_deps
${lib.concatMapAttrsStringSep "\n" (
name: src: "cp -r --no-preserve=ownership,mode ${src} build/_deps/${name}-src"
) deps}
'';
以上
と言うことで大雑把なメモは以上です。分かってしまえば簡単ですね(本当か?)