使用Nix构建含Rust/Python的Calyx依赖库遇nix-shell错误求助
问题背景
目标
尝试编写Nix derivation构建Calyx(同时运行所有测试验证构建/安装结果)。Calyx包含多个相互依赖的Rust和Python模块,各模块的构建测试需依赖其他模块构建完成。Python模块运行似乎需要源代码支持。
实现方案
- 使用
rustPlatform.buildRustPackage构建Rust子目录calyx,关闭测试检查 - 使用
pkgs.buildPythonPackage构建Python子目录calyx-py,关闭测试检查 - 使用
pkgs.buildPythonPackage构建Python子目录fud,关闭测试检查 - 使用
symlinkJoin将src(fud运行所需)与上述包链接在一起- 在
fixup阶段执行fud的配置步骤 - 在
installCheck阶段用单独构建的runt运行calyx和fud的检查
- 在
完整Nix表达式
{ # source code repo src, # nix stdlib lib, rustPlatform, # dependencies python3, python3Packages, runt, calyx, jq, z3, cvc5, whichSmt ? "z3", }: let srcTomlMeta = (builtins.fromTOML (builtins.readFile "${src}/Cargo.toml")).workspace.package; smt = if (whichSmt == "z3") then z3 else if (whichSmt == "cvc5") then cvc5 else throw "invalid value for `whichSmt`; must be either \"z3\" or \"cvc5\""; in rustPlatform.buildRustPackage { pname = "filament"; version = srcTomlMeta.version; inherit src; cargoPatches = [ ./add-Cargo.lock.patch ]; cargoHash = "sha256-VMsjEP4/ivVe2UrXuZvMuiEhIr8RruHOX/e2kL0CJgU="; nativeBuildInputs = [ python3 python3Packages.numpy runt calyx jq smt ]; patches = [ ./runt.toml.patch ]; doCheck = false; doInstallCheck = true; installCheckPhase = '' ln -s $out ./result runt -d rm ./result ''; meta = { inherit (srcTomlMeta) description homepage; license = lib.licenses.mit; platforms = lib.platforms.all; }; }
成功构建命令
nix-build -E 'let pkgs = import <nixpkgs> {}; in pkgs.callPackage ./calyx/package.nix {runt = pkgs.callPackage ./runt/package.nix {}; }'
遇到的问题
运行以下命令创建加载Calyx的nix-shell时报错:
nix-shell -E 'let pkgs = (import <nixpkgs> {}); in pkgs.mkShell { buildInputs = [pkgs.callPackage ./calyx/package.nix {runt = pkgs.callPackage ./runt/package.nix {}; } ]; }' --show-trace
错误信息:
error: Dependency is not of a valid type: element 1 of buildInputs for nix-shell
完整错误追踪:
error: … while calling the 'derivationStrict' builtin at <nix/derivation-internal.nix>:9:12: 8| 9| strict = derivationStrict drvAttrs; | ^ 10| … while evaluating derivation 'nix-shell' whose name attribute is located at /nix/store/lbmzs66dzl6vp7klrplq0c607s7majp9-source/pkgs/stdenv/generic/make-derivation.nix:336:7 … while evaluating attribute '__impureHostDeps' of derivation 'nix-shell' at /nix/store/lbmzs66dzl6vp7klrplq0c607s7majp9-source/pkgs/stdenv/generic/make-derivation.nix:451:7: 450| __propagatedSandboxProfile = unique (computedPropagatedSandboxProfile ++ [ propagatedSandboxProfile ]); 451| __impureHostDeps = computedImpureHostDeps ++ computedPropagatedImpureHostDeps ++ __propagatedImpureHostDeps ++ __impureHostDeps ++ stdenv.__extraImpureHostDeps ++ [ | ^ 452| "/dev/zero" … while calling the 'foldl'' builtin at /nix/store/lbmzs66dzl6vp7klrplq0c607s7majp9-source/pkgs/stdenv/generic/make-derivation.nix:435:11: 434| computedImpureHostDeps = 435| unique (concatMap (input: input.__propagatedImpureHostDeps or []) | ^ 436| (stdenv.extraNativeBuildInputs … while calling the 'concatMap' builtin at /nix/store/lbmzs66dzl6vp7klrplq0c607s7majp9-source/pkgs/stdenv/generic/make-derivation.nix:435:19: 434| computedImpureHostDeps = 435| unique (concatMap (input: input.__propagatedImpureHostDeps or []) | ^ 436| (stdenv.extraNativeBuildInputs … while calling anonymous lambda at /nix/store/lbmzs66dzl6vp7klrplq0c607s7majp9-source/pkgs/stdenv/generic/make-derivation.nix:435:30: 434| computedImpureHostDeps = 435| unique (concatMap (input: input.__propagatedImpureHostDeps or []) | ^ 436| (stdenv.extraNativeBuildInputs … from call site at /nix/store/lbmzs66dzl6vp7klrplq0c607s7majp9-source/pkgs/stdenv/generic/make-derivation.nix:435:37: 434| computedImpureHostDeps = 435| unique (concatMap (input: input.__propagatedImpureHostDeps or []) | ^ 436| (stdenv.extraNativeBuildInputs … while calling anonymous lambda at /nix/store/lbmzs66dzl6vp7klrplq0c607s7majp9-source/pkgs/stdenv/generic/make-derivation.nix:312:13: 311| (map (drv: getDev drv.__spliced.hostHost or drv) (checkDependencyList "depsHostHost" depsHostHost)) 312| (map (drv: getDev drv.__spliced.hostTarget or drv) (checkDependencyList "buildInputs" buildInputs')) | ^ 313| ] … from call site at /nix/store/lbmzs66dzl6vp7klrplq0c607s7majp9-source/pkgs/stdenv/generic/make-derivation.nix:312:18: 311| (map (drv: getDev drv.__spliced.hostHost or drv) (checkDependencyList "depsHostHost" depsHostHost)) 312| (map (drv: getDev drv.__spliced.hostTarget or drv) (checkDependencyList "buildInputs" buildInputs')) | ^ 313| ] … while calling 'getOutput' at /nix/store/lbmzs66dzl6vp7klrplq0c607s7majp9-source/lib/attrsets.nix:1797:23: 1796| */ 1797| getOutput = output: pkg: | ^ 1798| if ! pkg ? outputSpecified || ! pkg.outputSpecified … while evaluating a branch condition at /nix/store/lbmzs66dzl6vp7klrplq0c607s7majp9-source/lib/attrsets.nix:1798:5: 1797| getOutput = output: pkg: 1798| if ! pkg ? outputSpecified || ! pkg.outputSpecified | ^ 1799| then pkg.${output} or pkg.out or pkg … in the left operand of the OR (||) operator at /nix/store/lbmzs66dzl6vp7klrplq0c607s7majp9-source/lib/attrsets.nix:1798:32: 1797| getOutput = output: pkg: 1798| if ! pkg ? outputSpecified || ! pkg.outputSpecified | ^ 1799| then pkg.${output} or pkg.out or pkg … in the argument of the not operator at /nix/store/lbmzs66dzl6vp7klrplq0c607s7majp9-source/lib/attrsets.nix:1798:10: 1797| getOutput = output: pkg: 1798| if ! pkg ? outputSpecified || ! pkg.outputSpecified | ^ 1799| then pkg.${output} or pkg.out or pkg … from call site at /nix/store/lbmzs66dzl6vp7klrplq0c607s7majp9-source/pkgs/stdenv/generic/make-derivation.nix:312:25: 311| (map (drv: getDev drv.__spliced.hostHost or drv) (checkDependencyList "depsHostHost" depsHostHost)) 312| (map (drv: getDev drv.__spliced.hostTarget or drv) (checkDependencyList "buildInputs" buildInputs')) | ^ 313| ] … while calling anonymous lambda at /nix/store/lbmzs66dzl6vp7klrplq0c607s7majp9-source/lib/lists.nix:334:29: 333| */ 334| imap1 = f: list: genList (n: f (n + 1) (elemAt list n)) (length list); | ^ 335| … from call site at /nix/store/lbmzs66dzl6vp7klrplq0c607s7majp9-source/lib/lists.nix:334:32: 333| */ 334| imap1 = f: list: genList (n: f (n + 1) (elemAt list n)) (length list); | ^ 335| … while calling anonymous lambda at /nix/store/lbmzs66dzl6vp7klrplq0c607s7majp9-source/pkgs/stdenv/generic/make-derivation.nix:281:15: 280| imap1 281| (index: dep: | ^ 282| if isDerivation dep || dep == null || builtins.isString dep || builtins.isPath dep then dep … while calling the 'throw' builtin at /nix/store/lbmzs66dzl6vp7klrplq0c607s7majp9-source/pkgs/stdenv/generic/make-derivation.nix:284:14: 283| else if isList dep then checkDependencyList' ([index] ++ positions) name dep 284| else throw "Dependency is not of a valid type: ${concatMapStrings (ix: "element ${toString ix} of ") ([index] ++ positions)}${name} for ${attrs.name or attrs.pname}" | ^ 285| deps; error: Dependency is not of a valid type: element 1 of buildInputs for nix-shell
疑问
- 该错误的含义是什么?
- 操作哪里有误?如何用Nix正确构建这个包?
解答
1. 错误含义解析
这个错误表示你传递给buildInputs的某个元素不是Nix认可的有效依赖类型。Nix接受的有效依赖类型包括:
- Derivation(Nix构建输出的标准包)
- null
- 字符串(通常是本地路径或环境变量配置)
- 本地文件路径
你的情况是buildInputs中的元素不符合上述类型,导致Nix无法完成依赖解析。
2. 问题根源与修复方案
问题根源
你的Nix表达式存在循环依赖:在构建filament包时,nativeBuildInputs中声明了calyx参数,但调用callPackage时又将这个包本身作为calyx参数传入,导致生成了一个递归的无效结构,而非正常的derivation,最终被mkShell检测为无效依赖。
另外,你的实现思路和实际代码不匹配:你描述要构建calyx、calyx-py、fud三个模块后链接,但实际代码只构建了filament,且错误地将自身作为依赖传入。
修复步骤
步骤1:拆分各模块的独立构建
分别为三个核心模块编写单独的derivation:
1.1 Calyx Rust模块(calyx/default.nix)
{ lib, rustPlatform, src }: rustPlatform.buildRustPackage { pname = "calyx"; version = (builtins.fromTOML (builtins.readFile "${src}/Cargo.toml")).workspace.package.version; src = "${src}/calyx"; cargoLock.lockFile = "${src}/calyx/Cargo.lock"; cargoHash = "sha256-..."; # 替换为实际的cargo hash doCheck = false; # 后续测试通过后可开启 }
1.2 Calyx Python模块(calyx-py/default.nix)
{ lib, buildPythonPackage, src, calyx }: buildPythonPackage { pname = "calyx-py"; version = (builtins.fromTOML (builtins.readFile "${src}/Cargo.toml")).workspace.package.version; src = "${src}/calyx-py"; propagatedBuildInputs = [ calyx ]; doCheck = false; }
1.3 Fud工具(fud/default.nix)
{ lib, buildPythonPackage, src, calyx, calyx-py, python3Packages, jq, z3 }: buildPythonPackage { pname = "fud"; version = (builtins.fromTOML (builtins.readFile "${src}/Cargo.toml")).workspace.package.version; src = "${src}/fud"; propagatedBuildInputs = [ calyx calyx-py python3Packages.click python3Packages.requests python3Packages.numpy jq z3 ]; doCheck = false; postInstall = '' # 初始化fud配置 fud config global.cache-directory "$out/.fud-cache" ''; }
步骤2:编写整合包
创建整合包,将三个模块和源码链接(解决fud需要源码的问题):
{ lib, symlinkJoin, calyx, calyx-py, fud, src }: symlinkJoin { name = "calyx-full-${calyx.version}"; paths = [ calyx calyx-py fud src ]; postBuild = '' # 让fud能找到源码中的配置文件 ln -s $src/fud/config $out/share/fud-config fud config global.config-dir "$out/share/fud-config" ''; }
步骤3:顶层调用文件(default.nix)
{ pkgs ? import <nixpkgs> {} }: let src = pkgs.fetchFromGitHub { owner = "calyxir"; repo = "calyx"; rev = "..."; # 替换为你使用的版本号
相关产品推荐
相关产品推荐

