【问题标题】:How to specify package/derivation runtime dependencies with Nix?如何使用 Nix 指定包/派生运行时依赖项?
【发布时间】:2021-09-20 13:14:19
【问题描述】:

我正在制作一个 haskell 程序,我正在设置 buildInput 像这样包含 pkgs.ffmpeg-full

(myHaskellPackages.callCabal2nix "App" (./.) {}).overrideAttrs (oldAttrs: {
  buildInputs = (oldAttrs.buildInputs or []) ++ [ pkgs.ffmpeg-full ];
})

然而,这似乎使得 ffmpeg 包只能在构建时访问,而不是在应用程序的运行时访问。

我需要设置什么属性才能使ffmpeg-full 在运行时可用 - 能够调用ffmpeg 可执行文件?

nix 丸中有一个关于运行时依赖的部分,但我不明白那个部分,它如何总是通过哈希来确定运行时依赖是没有意义的?我的意思是,如果我在 shell 脚本中引用可执行文件 - nix 肯定不会解析 shell 脚本来确定我引用的可执行文件。 https://nixos.org/guides/nix-pills/automatic-runtime-dependencies.html#idm140737320205792

但是,运行时依赖项有些不同。建造 Nix 自动识别依赖项 任何派生调用,但我们从不指定什么是运行时 派生的依赖项。

确实涉及到黑魔法。起初是这样的 一瞥让你觉得“不,这不能长期工作”,但在 同时它运行良好,以至于构建了一个完整的操作系统 在这个魔法之上。

换句话说,Nix 会自动计算所有运行时 派生的依赖关系,这可能要归功于 商店路径。

【问题讨论】:

  • 是的,nix 确实会扫描您的输出以查找哈希值。如前所述,它工作得非常好。我从来没有遇到过任何问题。
  • "要让 ffmpeg-full 在运行时可用吗?"您需要什么取决于您是链接到它还是调用可执行文件。
  • 在这种情况下,它正在调用一个可执行文件。
  • 我可以要求一个可运行的minimal reproducible example吗?在 Cabal 构建中使用 nixpkgs makeWrapper 有一些 Haskell 特有的复杂性。

标签: nix


【解决方案1】:

default.nix:

{
  ghc ? "ghc8106",
  pkgs ? import <nixpkgs> {}
}:
with pkgs.haskell.lib;
let
  haskellPkgs = pkgs.haskell.packages.${ghc};
  inherit (pkgs) lib;

  mySourceRegexes = [
    "^app.*$"
    "^.*\\.cabal$"
    "package.yaml"
  ];

  myApp = (haskellPkgs.callCabal2nix "my-hello"
    (lib.sourceByRegex ./. mySourceRegexes) { });

in myApp
   .overrideAttrs(
      oa: {
        nativeBuildInputs = oa.nativeBuildInputs ++ [pkgs.hello pkgs.makeWrapper];
        installPhase = oa.installPhase + ''
          ln -s ${pkgs.hello.out}/bin/hello $out/bin/hello
        '';
        postFixup = ''
          wrapProgram $out/bin/x-exe --prefix PATH : ${pkgs.lib.makeBinPath [ pkgs.hello ]}
        '';
      })

src/Main.hs:

module Main where

import System.Process (callCommand)

main :: IO ()
main = do
  putStrLn "HELLO"
  callCommand "hello"
  putStrLn "BYE"

【讨论】:

  • 这似乎有 0 次提到 ffmpeg,这是我试图添加的依赖项?
  • 这是任何可执行文件的通用版本,用 ffmpeg 替换 hello
【解决方案2】:

似乎没有明确声明的依赖项列表直接支持这一点。但是我们可以通过“包装”间接实现这一点。


我在这里找到了更多关于包装的信息:https://nixos.wiki/wiki/Nix_Cookbook#Wrapping_packages

所以我可以做一个引用包的ls

...
appPkg = (myHaskellPackages.callCabal2nix "HaskellNixCabalStarter" (./.) {}).overrideAttrs (oldAttrs: {
  buildInputs = (oldAttrs.buildInputs or []) ++ [ pkgs.ffmpeg-full ];
  });
in
(pkgs.writeScriptBin "finderapp" ''
  #!${pkgs.stdenv.shell}

  ls ${pkgs.ffmpeg-full}/bin/ffmpeg
  exec ${appPkg}/bin/app
''
)

我们可以验证构建的包(?)是否正确取决于适当的:

nix-store -q --references result
/nix/store/0cq84xic2absp75ciajv4lfx5ah1fb59-ffmpeg-full-4.2.2
/nix/store/rm1hz1lybxangc8sdl7xvzs5dcvigvf7-bash-4.4-p23
/nix/store/wlvnjx53xfangaa4m5rmabknjbgpvq3d-HaskellNixCabalStarter-0.1.0.0

【讨论】:

  • 我不确定您在这里所做的是否构成以一种特别有用的方式包装您的脚本。请参阅创建更新 PATH 的包装脚本的 nixpkgs 帮助程序,然后调用您的“真实”脚本(以不同的名称)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多