ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

nixpkgs 增量构建指南:用 pkgs.checkpointBuildTools 实现检查点(Checkpoint)构建

nixpkgs 增量构建指南:用 pkgs.checkpointBuildTools 实现检查点(Checkpoint)构建 nixpkgs 增量构建指南用 pkgs.checkpointBuildTools 实现检查点Checkpoint构建【免费下载链接】nixpkgsNix Packages collection NixOS项目地址: https://gitcode.com/GitHub_Trending/ni/nixpkgspkgs.checkpointBuildTools是 nixpkgs 提供的一组构建辅助工具它通过把「上一次构建的状态」显式表达为一个 derivation 输出让 Nix 得以在严格封闭hermetic的构建环境中实现派生derivation级别的增量构建。本文以 doc/build-helpers/special/checkpoint-build.section.md 为骨架结合 checkpoint-build.nix 的完整实现讲解prepareCheckpointBuild与mkCheckpointBuild两个函数的工作原理、使用步骤与源码级细节帮助你在大源码包如 VirtualBox、Linux 内核这类编译耗时的项目上获得更短的迭代构建时间。Nix 的封闭性困境为什么默认无法增量构建Nix 的构建环境是封闭hermetic的一次构建不允许把任何状态携带到下一次构建中。这意味着同一条 derivation 每次从零开始执行构建阶段因此在一个 derivation 内部做「透明」的增量编译在默认情况下是不可能的。pkgs.checkpointBuildTools提供了一种绕开该限制的显式方案——把「前一次构建的状态」当作 derivation 的一个输出保存下来然后在新的构建中把这个状态当作输入使用。由于状态本身变成了 Nix store 中可引用的产物封闭性没有被破坏但增量构建成为可能。从源码结构看整个工具由两个函数组成均定义在 checkpoint-build.nix 中并通过 all-packages.nix 中的checkpointBuildTools callPackage ../build-support/checkpoint-build.nix { };暴露为pkgs.checkpointBuildTools。将普通 derivation 改造为检查点构建的四个步骤官方文档给出了把普通 derivation 改成基于检查点构建的标准流程先用prepareCheckpointBuild对原始包生成一次「检查点产物」{ checkpointArtifacts (pkgs.checkpointBuildTools.prepareCheckpointBuild pkgs.virtualbox); }用overrideAttrs得到你真正想改动的派生版本例如替换源码{ changedVBox pkgs.virtualbox.overrideAttrs (old: { src path/to/vbox/sources; }); }调用mkCheckpointBuild changedVBox checkpointArtifacts把两者组合起来。享受更短的构建时间。这套流程的关键在于检查点产物只生成一次之后对源码或构建参数的每次修改都可以在已有产物的基础上做增量构建而不是全量重编。完整示例改造 hello 的源码并增量重建原文档给出了一个可直接运行的最小示例基于pkgs.hello先用prepareCheckpointBuild生成检查点再通过overrideAttrs修改源码与构建行为最后用mkCheckpointBuild组合{ pkgs ? import nixpkgs { }, }: let inherit (pkgs.checkpointBuildTools) prepareCheckpointBuild mkCheckpointBuild; helloCheckpoint prepareCheckpointBuild pkgs.hello; changedHello pkgs.hello.overrideAttrs (_: { doCheck false; postPatch sed -i s/Hello, world!/Hello, Nix!/g src/hello.c ; }); in mkCheckpointBuild changedHello helloCheckpoint要点拆解prepareCheckpointBuild pkgs.hello会执行一次完整的 hello 构建并把「构建前的源码状态」与「构建完成后的输出目录」都存入产物。changedHello通过overrideAttrs关闭测试doCheck false并利用postPatch阶段把输出文案Hello, world!改为Hello, Nix!。mkCheckpointBuild changedHello helloCheckpoint生成最终 derivation它在预构建阶段比对新旧源码差异、恢复上一次的输出文件、再把差异 patch 回去——此时只有被修改过的部分hello.c需要重新编译。注意检查点构建适合本地开发迭代场景。由于它会读写大体积的构建目录快照并依赖diff/rsync/patch等本地工具并不适合作为 CI 中替代常规全量构建的手段。源码级解析prepareCheckpointBuild 如何保存构建状态prepareCheckpointBuild的实现见 checkpoint-build.nix本质上是对原 derivation 的overrideAttrs一次性把「状态快照」固化到输出中输出与命名将outputs强制设为[ out ]并把名称改为drv.name -checkpointArtifacts与原始包区分开。保存构建前源码在preBuild中执行mkdir -p $out/sources与cp -r ./* $out/sources/把「构建目录在 patch 阶段之后、构建开始之前」的状态完整保存下来。文档注释特别说明这样同一个 derivation 可以被反复复用后续构建只需检测差异即可即便文件被删除也能在后续构建中被正确处理。保存构建后输出installPhase中执行mkdir -p $out/outputs与cp -r ./* $out/outputs/把完整的构建目录而非仅安装产物复制到outputs。之所以复制整个构建目录是为了兼容那些在源码目录内直接构建、没有独立 build 目录的工具如 Linux 内核。preCheckpointInstall/postCheckpointInstall两个 hook 保留了扩展点。关闭无关阶段设置dontFixup true、doInstallCheck false、doDist false跳过打补丁fixup、安装检查和 dist 阶段保证快照内容与原始构建阶段的目录状态一致。源码级解析mkCheckpointBuild 如何应用差异实现增量mkCheckpointBuild见 checkpoint-build.nix同样通过overrideAttrs在原有preBuild之前注入一段增量恢复逻辑set e sourceDifferencePatchFile$(${mktemp}/bin/mktemp) diff -ur ${checkpointArtifacts}/sources ./ $sourceDifferencePatchFile set -e shopt -s dotglob rm -r * ${rsync}/bin/rsync \ --checksum --times --atimes --chown$USER:$USER --chmodw \ -r ${checkpointArtifacts}/outputs/ . patch -p 1 -i $sourceDifferencePatchFile rm $sourceDifferencePatchFile逐行含义如下比对差异diff -ur对比检查点中的sources旧状态与当前构建目录新状态已应用过postPatch等阶段把差异写入临时文件。注释明确说明这一步的目的正是「用补丁文件表达前后两次源码的变化」。清理目录shopt -s dotglob开启后rm -r *连隐藏文件一并删除确保旧状态被彻底清空。恢复输出用rsync把检查点的outputs目录整体复制回当前构建目录同时保留--checksum --times --atimes的元数据语义并--chown$USER:$USER --chmodw保证文件归属与可写性。应用差异patch -p 1 -i $sourceDifferencePatchFile把「从旧状态到新状态」的改动补丁打回去使构建目录既包含上一次构建的成果又包含这次修改的内容——之后的编译阶段就只需要重新编译发生变化的文件从而显著缩短构建时间。其中mktemp与rsync取自buildPackages而不是目标平台包这是为了对交叉编译cross-compilation提供基础支持相关设计说明可在 checkpoint-build.nix 顶部的注释中看到。兼容性与注意事项废弃别名当config.allowAliases开启时模块还提供mkCheckpointedBuild作为mkCheckpointBuild的兼容别名并在使用时会通过lib.warn输出 mkCheckpointedBuildis deprecated, usemkCheckpointBuildinstead! 的弃用警告见 checkpoint-build.nix。新代码应直接使用mkCheckpointBuild。适用于「源码内构建」的项目由于输出快照保存的是完整构建目录对于直接在源码目录编译的项目如内核类尤其合适因为工具作者在实现时已针对这类构建方式做了专门设计。本地迭代用途检查点构建是为缩短「同一工程反复修改后的本地重建」时间而设计的增量方案它依赖派生输出的显式传递并不会破坏 Nix 的封闭性保证。进一步阅读官方文档原文doc/build-helpers/special/checkpoint-build.section.md完整实现源码pkgs/build-support/checkpoint-build.nix工具注册位置pkgs/top-level/all-packages.nix同类构建辅助工具总览doc/build-helpers/special.md【免费下载链接】nixpkgsNix Packages collection NixOS项目地址: https://gitcode.com/GitHub_Trending/ni/nixpkgs创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表