1 automatic runtime
分析构建时依赖和运行时依赖
build dependencynix-instantiate hellov2.nix/nix/store/3g7ccvlxrpmb2s9m4vkasz8y6444fwsc-hello.drvnix-store -q --references /nix/store/3g7ccvlxrpmb2s9m4vkasz8y6444fwsc-hello.drv/nix/store/3077wznnjrbd318k17j7fjsgxy9xgrcl-gnutar-1.35.drv /nix/store/3mdqlcjhflm8mdm2192bap27g8zv60sq-generic-builder.sh /nix/store/982f8csn028v499k0fkrl66x28cbj3b8-bash-5.2-p15.drv /nix/store/dxsdysn7gpyjajiqjvab03bilarjjn15-coreutils-9.3.drv /nix/store/f7glbcn7n59k22b911bx1vyy13g4bdxh-binutils-2.40.drv /nix/store/fimilhby9fyqbfwmw826id3hwfhya6qx-hello-2.12.1.tar.gz /nix/store/fis965lcaxlhxsibjqr7g99l074niraj-gnumake-4.4.1.drv /nix/store/jhkn3namnqqkl7hmxmcml0ffir0dv774-gnugrep-3.11.drv /nix/store/n20wzc7mdmdq91vq5b6gklsz1171k82r-gnused-4.9.drv /nix/store/w1nk39ahhnzkj9yqa5vpggxgff11056g-gawk-5.2.2.drv /nix/store/w3f8imf2csiwc7jfinmgf682rvhg7fna-gcc-wrapper-12.3.0.drv /nix/store/zq7wlgpchcp0857swj8jv5hdwk0pzlg7-gzip-1.12.drvruntime dependencyderivation的运行时依赖是由Nix自动识别的- 把derivation的out path序列化为NAR
- 对derivation的每个构建时依赖及其对应的out path,在NAR中寻找该out path的hash部分
- 如果找到了,说明这个out path是该derivation的运行时依赖
通过
nix-store -r /nix/store/3g7ccvlxrpmb2s9m4vkasz8y6444fwsc-hello.drv得到out path/nix/store/x3skf9wy7hpigvp8dca7kg1xafwhy5gv-hello用nix-store -q --references /nix/store/x3skf9wy7hpigvp8dca7kg1xafwhy5gv-hello得到运行时依赖1 2 3 4 5/nix/store/vq3sdi8l15rzfl5zvmwpafrzis4sm6xf-glibc-2.37-8 /nix/store/c50v7bf341jsza0n07784yvzp5fzjpn5-gcc-12.3.0-lib /nix/store/kmp7p16z94gx9nm80n03j8cp9rllmla2-glibc-2.37-8-dev /nix/store/nd4dhnbh1wagnxh2fzd3cqb8ifzl2r43-gcc-12.3.0 /nix/store/x3skf9wy7hpigvp8dca7kg1xafwhy5gv-hello嗯..glibc,gcc.. !? gcc, 我编译好的hello程序为啥还依赖gcc啊?
strings result/bin/hello | grep gcc1 2/nix/store/vq3sdi8l15rzfl5zvmwpafrzis4sm6xf-glibc-2.37-8/lib:/nix/store/c50v7bf341jsza0n07784yvzp5fzjpn5-gcc-12.3.0-lib/lib /nix/store/nd4dhnbh1wagnxh2fzd3cqb8ifzl2r43-gcc-12.3.0/lib/gcc/x86_64-unknown-linux-gnu/12.3.0/include还真依赖gcc 第一个是
ldrpath,是用来在运行时寻找库文件的地方(对nix来说这是必须的,因为它不存在全局,不硬编码的话程序不知道位置) 但是我们并不需要这个这个运行时库。可以通过patchelf来修改二进制来除去rpath。同时也需要用strip来去除调试表(这也使得其依赖gcc)这些操作可以在
generic-builder.sh中完成,加条fixupPhase(别忘了在hellov2.nix的buildInputs中加入findutils和patchelf作为构建依赖)1 2# fixup find $out -type f -exec patchelf --shrink-rpath '{}' \; -exec strip '{}' \; 2>/dev/null通过
nix build --file hellov2.nix --print-out-paths得到out path:/nix/store/vsrbxvz5psf44gdj7bq3wh0mwzqpx34w-hello再通过
nix-store -q --references /nix/store/vsrbxvz5psf44gdj7bq3wh0mwzqpx34w-hello得到此时的运行时依赖:1 2/nix/store/vq3sdi8l15rzfl5zvmwpafrzis4sm6xf-glibc-2.37-8 /nix/store/vsrbxvz5psf44gdj7bq3wh0mwzqpx34w-hello哈哈,gcc没有啦! great :)
package is self-contained复制一个包的运行时闭包到另一系统上能够直接运行(因为该包不依赖复制到的系统上的gcc(通过ldd result/bin/hello能够清楚地看到这一点)), 其只依赖在构建时的特定位置和版本(/nix/store)中的gcc 总之,Nix打出的包是自包含的题外话:
NAR(Nix ARchive) 为什么不用已有的归档格式(tar等)? 它们都具有不确定性(不排序,添加时间戳…) NAR符合Nix,是reproducible的 可以通过nix-store --dumpnix-store --restorenix nar ...nix store dump-path来管理NAR