将最新版本的软件包与nix配合使用

问题描述

我正在尝试为我的应用设置一个依赖于asiofmt的nix构建脚本(暂时跳过第一个脚本,因为这是一个更复杂的故事)。它们不是最新的nix软件包,所以我不能简单地从那里获取它。

但是我意识到它基本上是另一个nix文件,应该可以将其嵌入到我的项目中,因此将在之前建立依赖关系。

我尝试将其嵌入default.nix文件中,但这种方式行不通。

with import <nixpkgs> {};


stdenv.mkDerivation rec {
  pname = "fmt";
  version = "7.0.3";

  outputs = [ "out" "dev" ];

  src = fetchFromGitHub {
    owner = "fmtlib";
    repo = "fmt";
    rev = version;
  };


  nativeBuildInputs = [ cmake ];

  cmakeFlags = [
    "-DBUILD_SHARED_LIBS=ON"
    "-DCMAKE_SKIP_BUILD_RPATH=OFF" # for tests
  ];
}

stdenv.mkDerivation {
  name = "my-app";
  src = ./.;

  buildInputs = [ fmt ];

  buildPhase = "c++ -o main main.cpp -lfmt";
}

如何安装该软件包的最新/所需版本?

如何组合多个派生并依赖它们?

解决方法

简短的回答:您需要使用let绑定。 (长答案:使用单独的文件+ callPackage,请参见下文)

with import <nixpkgs> {};

# create a binding for fmt (which is like an assignment but declarative)
let fmt = stdenv.mkDerivation rec {
  pname = "fmt";
  version = "7.0.3";

  outputs = [ "out" "dev" ];

  src = fetchFromGitHub {
    owner = "fmtlib";
    repo = "fmt";
    rev = version;
  };


  nativeBuildInputs = [ cmake ];

  cmakeFlags = [
    "-DBUILD_SHARED_LIBS=ON"
    "-DCMAKE_SKIP_BUILD_RPATH=OFF" # for tests
  ];
}
# terminate your bindings with the `in` keyword. The following expression is returned
in
stdenv.mkDerivation {
  name = "my-app";
  src = ./.;

  buildInputs = [ fmt ];

  buildPhase = "c++ -o main main.cpp -lfmt";
}

callPackage

我建议复制整个文件,以保持可读性。

Nixpkgs中的包通常在文件中描述,这些文件本身不是可构建的表达式(即返回派生),而是从包到派生的函数。因此,从本质上讲,您需要将函数与包集一起应用,但是我们使用pkgs.callPackage函数代替常规函数应用程序,该函数负责反映参数,因此您不必使用{{1} }语法并添加{ x,... }:属性。

它还允许覆盖程序包并通过第二个参数传递额外的参数。

override

或者在您的情况下仅使用pkgs.callPackage ./fmt.nix {} ,因为您已经在callPackagewith)上使用了pkgs关键字。

我通常建议避免使用let pkgs = import <nixpkgs> {}; in关键字,因为它不必要地使Nix的范围规则变得复杂,并且对于没有将Nix评估器插入我们大脑的人类来说,它会使查找绑定变得更加困难。