Nixpkgs 中的 Scheme 包管理:Akku 集成与 akkuPackages 使用指南
【免费下载链接】nixpkgsNix Packages collection & NixOS项目地址: https://gitcode.com/GitHub_Trending/ni/nixpkgs
本篇技术指南聚焦 Nixpkgs 中 Scheme 生态的包管理方案——基于 Akku(Akku.scm)语言包管理器构建的akkuPackages属性集。读者将掌握如何在 Nix 派生(derivation)与nix-shell中使用约两百个 R6RS/R7RS 库,理解包索引deps.toml的生成与更新机制,并从源码层面看懂 Nixpkgs 如何将 Akku 包体系接入标准构建流程。
Akku 与 Nixpkgs 的集成概览
Akku 是面向 Scheme 语言的语言级包管理器,其官方仓库同时镜像了 snow-fort(snow-fort.org/pkg)的包源。Nixpkgs 将 Akku 的包索引整体收入仓库,提供两层产物:
akku:Akku 可执行程序本身,位于顶层属性集,可直接安装使用(见 all-packages.nix 中inherit (recurseIntoAttrs (callPackage ../tools/package-management/akku { })) akku akkuPackages);akkuPackages:由约两百个 R6RS 与 R7RS 库组成的包集合,每个包都是一个标准的 Nix 派生,可被放入其他派生(derivation)的buildInputs,也能够在nix-shell中正常工作。
这些包在构建期使用Chez Scheme与Chibi Scheme执行测试,从而保证进入 Nixpkgs 的包不仅可安装,还通过了上游自带测试用例的验证。
将 Akku 包用作构建输入
在 Nix 中引入一个 Akku 包的方式与引入任何常规 Nix 包完全一致——写入buildInputs。原文档给出的示例是为一组主要面向 Chez Scheme 的 SRFI 库(akkuPackages.chez-srfi)准备的:
{ buildInputs = [ chez akkuPackages.chez-srfi ]; }这里chez提供 Chez Scheme 解释器,akkuPackages.chez-srfi提供 SRFI 库本体。两者同时出现在buildInputs中即可让派生在构建、测试与安装阶段找到对应的库路径。
为什么 nix-shell 中也能直接使用
Nixpkgs 为 Akku 包配备了一个 setup-hook.sh,这是其“放进buildInputs即生效”的关键。该钩子遍历一份覆盖主流 Scheme 实现的库搜索环境变量列表:
CHEZSCHEMELIBDIRS GUILE_LOAD_PATH IKARUS_LIBRARY_PATH MOSH_LOADPATH PLTCOLLECTS SAGITTARIUS_LOADPATH VICARE_SOURCE_PATH YPSILON_SITELIB LARCENY_LIBPATH IRONSCHEME_LIBRARY_PATH LOKO_LIBRARY_PATH DIGAMMA_SITELIB CHIBI_MODULE_PATH GAUCHE_LOAD_PATH对每个变量,钩子都会通过addToSearchPath把包的lib/scheme-libs目录追加进去;同时对 Guile 还会追加lib/libobj(编译产物)到GUILE_LOAD_COMPILED_PATH,对 FFI 目录分别追加LD_LIBRARY_PATH与DYLD_LIBRARY_PATH。从源码结构看,这意味着同一份包输出可以同时服务于 Chez、Guile、Chibi、Racket(PLTCOLLECTS)、Gauche 等多个实现——无论用户把包放进buildInputs还是通过nix-shell引入,对应解释器都能自动解析到这些库。
akkuPackages 的构建机制
akkuPackages并非手工编写的包列表,而是由一个统一的构建函数批量生成。其定义位于 default.nix:
- 使用
lib.makeScope newScope建立独立作用域,作用域内包含akku(可执行程序)、akkuDerivation(通用构建函数)与akkuPackages; deps = lib.importTOML ./deps.toml将包索引文件直接导入为 Nix 数据结构;lib.mapAttrs (makeAkkuPackage akkuself) deps为索引中的每个条目调用makeAkkuPackage,生成对应的 Nix 派生;- 最后通过
lib.recurseIntoAttrs packages让整个集合在 Hydra 等批量求值场景中可被递归遍历。
通用构建函数 akkuDerivation
akkuDerivation.nix 是每个 Akku 包派生背后的通用模板,其核心逻辑如下:
构建阶段(buildPhase):先删除上游的Akku.lock与Akku.manifest,再执行akku install拉取并安装依赖;随后用 Guile 运行仓库自带的 parse-akku.scm(merge模式)扫描CHEZSCHEMELIBDIRS下所有metadata.sls,把当前包的名称、版本与已安装库清单合并写回.akku/lib/akku/metadata.sls,确保测试与后续使用阶段元数据完备。
测试阶段(checkPhase):doCheck = true默认开启测试。构建时分别导出CHEZSCHEMELIBDIRS与CHIBI_MODULE_PATH指向.akku/lib,随后遍历两类测试文件:
- 所有
test*目录下的.sps文件; - 所有匹配
run-test的.scm文件。
执行方式按包类型区分:可执行文件直接运行;r7rs = true的包用chibi-scheme运行;其余用scheme-script(Chez)运行。这正是原文档所述“使用 Chez 与 Chibi Scheme 在构建期测试”的具体实现。若测试文件被列入SKIP环境变量则跳过(如chez-srfi在 overrides.nix 中列出了若干已知失败的测试文件)。
安装阶段(installPhase):将.akku/lib复制为$out/lib/scheme-libs,.akku/bin复制为$out/bin;若存在ffi与libobj目录则一并复制;最后用patchShebangs修正脚本解释器,并用wrapProgram为每个可执行程序注入CHEZSCHEMELIBDIRS前缀,保证脱离构建环境后依然能找到库。
包的属性来源:deps.toml 与 overrides.nix
每个包派生所需的version、url、sha256、dependencies、dev-dependencies、license、source、synopsis等属性全部来自 deps.toml(当前索引含三千余行条目)。例如:
[arvyy-mustache] dependencies = ["akku-r7rs", "chez-srfi"] dev-dependencies = [] license = "mit" url = "http://snow-fort.org/s/gmail.com/nma.arvydas.silanskas/arvyy/mustache/1.0.2/arvyy-mustache-1.0.2.tgz" sha256 = "ea8085f6313851249dc41e86a5c455225f73f351046994296fe7fc6144f05d16" source = "snow-fort" synopsis = "Mustache templating 1.2.1 implementation" version = "1.0.2"makeAkkuPackage会据此构造派生:
src = fetchurl { inherit url sha256; },unpackPhase = "tar xf $src";buildInputs由dependencies映射到作用域内的其他 Akku 包(map (x: akkuself.${x}) dependencies);dev-dependencies进入nativeBuildInputs;r7rs = source == "snow-fort":来自 snow-fort 的包按 R7RS 处理,来自 Akku 官方归档的按 R6RS 处理;license字符串经stringToLicense映射表(覆盖 bsd0、agpl、asl20、gpl 系列、lgpl 系列、cc0、publicDomain、srfi 等 30 余种 SPDX 标识)转换为 Nix 的 license 对象,支持列表形式的多许可。
随后通过overrideAttrs应用 overrides.nix 中按包名定制的修补:例如chez-srfi跳过特定测试、scheme-langserver在安装阶段补写 LSP 可执行入口、xyz-modem用command -v替换which并补充lrzsz检查依赖、大量已知失效的包(如chibi-ssl、srfi-64、tex-parser等)被标记为broken、ufo-thread-pool在 Darwin 上标记 broken、wak-htmlprag在 aarch64 上标记 broken 等。这些覆盖是包集合“开箱即用”的质量保障层。
更新包索引:deps.toml 的刷新流程
Akku 包索引不会自动保持最新,需要周期性刷新。原文档说明索引位于pkgs/tools/package-management/akku目录下,文件名为deps.toml,更新方式是在该目录内执行./update.sh。
从源码看,update.sh 的完整逻辑是一条命令:
curl -sSf https://archive.akkuscm.org/archive/Akku-index.scm | guile parse-akku.scm deps > deps.toml即:从 Akku 官方归档服务器拉取最新的Akku-index.scm包索引,交给 Guile 执行 parse-akku.scm(deps模式)解析,重新生成deps.toml。该脚本以nix-shellshebang 方式声明运行环境(nix-shell -I nixpkgs=../../../../ -i bash -p guile curl),直接指向仓库自身的 nixpkgs 提供guile与curl。
parse-akku.scm 的解析逻辑
parse-akku.scm承担两个职责(通过命令行首个参数区分模式):
deps模式:逐条读取Akku-index.scm中的包记录,对每个包取versions列表中的最新版本,抽取license、url、sha256、depends(依赖)、depends/dev(开发依赖)、synopsis、version等字段,并按 URL 前缀判定source归属:以https://archive.akkuscm.org/开头记为akku,以http://snow-fort.org/开头记为snow-fort,否则记为UNKNOWN,最终输出为 TOML 格式写入deps.toml;merge模式:如前所述,在构建阶段合并多个包的installed-libraries与installed-assets元数据,生成去重后的metadata.sls。
刷新索引后,新包与新版本会出现在akkuPackages中,但需要留意:新包若存在构建或测试问题,通常需要在overrides.nix中登记相应的跳过测试、补丁或broken标记,这正是 Nixpkgs 维护者处理上游包质量差异的常规流程。
限制与注意事项
- 包数量与覆盖范围:
akkuPackages覆盖 Akku/snow-fort 索引中约两百个包,并非全部可用——大量包在 overrides.nix 中被显式标记broken(例如chibi-ssl、chibi-mecab、r6rs-clos、swish等),原因是测试失败、依赖缺失或不受支持的 Scheme 实现; - 运行时依赖:
akku程序本身在 akku.nix 中通过 Guile 3.0.10 构建(源码注释说明 Akku 目前自 Guile 3.0.11 起会构建失败,因此临时固定版本),并依赖curl与git作为运行时工具; - 版本语义:
akkuPackages中包名带akku-前缀(如akku-chez-srfi的pname实际为akku-chez-srfi),但用户访问时使用不带前缀的akkuPackages.chez-srfi形式,与构建产物名存在差异; - 更新节奏:
deps.toml需人工周期刷新,包版本并非实时镜像上游。
延伸阅读
- Scheme 语言框架文档:doc/languages-frameworks/scheme.section.md(本文依据)
- Akku 包集与构建函数定义:pkgs/tools/package-management/akku/default.nix
- 通用派生模板:pkgs/tools/package-management/akku/akkuDerivation.nix
- 包索引数据:pkgs/tools/package-management/akku/deps.toml
- 包级修补与 broken 标记:pkgs/tools/package-management/akku/overrides.nix
- 索引解析脚本:pkgs/tools/package-management/akku/parse-akku.scm
- 更新脚本:pkgs/tools/package-management/akku/update.sh
- 环境变量注入钩子:pkgs/tools/package-management/akku/setup-hook.sh
- Akku 本体打包:pkgs/tools/package-management/akku/akku.nix
【免费下载链接】nixpkgsNix Packages collection & NixOS项目地址: https://gitcode.com/GitHub_Trending/ni/nixpkgs
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考