我正在尝试为我的应用设置一个依赖于asio
和fmt
的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";
}
如何安装该软件包的最新/所需版本?
如何组合多个派生并依赖它们?
答案 0 :(得分:1)
简短的回答:您需要使用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 {}
,因为您已经在callPackage
(with
)上使用了pkgs
关键字。
我通常建议避免使用let pkgs = import <nixpkgs> {}; in
关键字,因为它不必要地使Nix的范围规则变得复杂,并且对于没有将Nix评估器插入我们大脑的人类来说,它会使查找绑定变得更加困难。