使用带有 nix 的最新版本的包

Use latest version of package with nix

我正在尝试为我的应用程序设置一个依赖于 asiofmt 的 nix 构建脚本(现在跳过第一个,因为它是一个更复杂的故事)。他们不是最新的 nix 包,所以我不能简单地从那里得到它。

但我意识到它基本上是另一个nix文件,应该很可能嵌入到我的项目中,所以de dependency会在之前构建。

我试过将它嵌入到 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";
}

如何安装latest/desired版本的包?

如何组合多个推导并依赖?

简答:您需要使用 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 函数而不是正常的函数应用程序,它负责反映参数所以你不必使用 { x, ... }: 语法并添加 override 属性。

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

pkgs.callPackage ./fmt.nix {}

或者在您的情况下只是 callPackage 因为您已经在本来可以称为 pkgs (let pkgs = import <nixpkgs> {}; in).[=22= 的内容上使用了 with 关键字]

我通常建议避免使用 with 关键字,因为它不必要地使 Nix 的作用域规则复杂化,并且它会使我们这些大脑中没有 Nix 求值器的人更难找到绑定。