如何在shell.nix中正确引用自定义Derivation并直接调用?
问题:在Nix Shell中直接调用自定义Derivation脚本失败
需求
我是Nix新手,希望在shell.nix中引用项目脚本,实现cd到项目目录后可直接通过名称调用,且源码变更时自动更新。
当前目录结构
project nix myScript default.nix builder.sh shell.nix
现有Derivation代码
myScript/default.nix
# default.nix { pkgs ? import <nixpkgs> {} }: pkgs.stdenv.mkDerivation rec { name = "myScript"; echo = pkgs.coreutils + "/bin/echo"; builder = "${pkgs.coreutils}/bin/bash"; args = [ ./builder.sh ]; }
myScript/builder.sh
# builder.sh $echo "$echo Hello world" > $out
运行nix-build myScript.nix后,生成的result符号链接指向的文件内容为:
/nix/store/3mfkgajns47hfv0diihzi2scwl4hm2fl-coreutils-9.1/bin/echo Hello world
尝试的shell.nix配置
{ pkgs ? import (fetchTarball "https://github.com/NixOS/nixpkgs/archive/bf972dc380f36a3bf83db052380e55f0eaa7dcb6.tar.gz") {} }: let myScript = import ./myScript {}; in pkgs.mkShell { buildInputs = [ myScript ]; shellHook = '' echo Loading shell.nix ''; }
遇到的错误
进入项目目录执行myScript时,报错:
zsh: command not found: myScript
已确认direnv配置正常(可加载其他shell工具并验证版本),问题出在Nix配置上。我知道可以用pkgs.writeShellScriptBin简化,但这只是示例,最终会使用更复杂的Derivation。
我的怀疑
myScript的Derivation或builder可能存在问题——虽然生成的输出文件加执行权限后可运行,但我怀疑需要告知Nix如何识别它,或是导入Derivation的方式有误。
解决方案
问题根源
你的Derivation只生成了单个可执行文件,但没有遵循Nix包的标准结构(将可执行文件放在bin目录下)。当把Derivation加入buildInputs时,Nix只会自动将Derivation输出中的bin目录添加到PATH,而你的脚本直接在输出根目录,所以系统找不到它。另外,当前配置没有监控源码变更,修改脚本后不会自动重新构建。
修复方案(保留builder.sh的方式)
修改myScript/default.nix
添加src字段监控源码变更,确保脚本修改后自动重建:
# myScript/default.nix { pkgs ? import <nixpkgs> {} }: pkgs.stdenv.mkDerivation rec { name = "myScript"; src = ./.; # 监控当前目录下的文件变更 echo = pkgs.coreutils + "/bin/echo"; builder = "${pkgs.coreutils}/bin/bash"; args = [ ./builder.sh ]; }
修改myScript/builder.sh
生成标准的bin目录结构,将脚本放入其中:
# builder.sh mkdir -p $out/bin echo "$echo Hello world" > $out/bin/myScript chmod +x $out/bin/myScript
验证
修改完成后,重新进入Nix Shell,执行myScript即可正常输出Hello world。后续修改builder.sh或default.nix时,Nix会自动重新构建Derivation,确保调用的是最新版本。
内容的提问来源于stack exchange,提问作者haz
相关产品推荐
相关产品推荐

