Reputation: 1547
I'm trying to setup a nix build script for my app which depends on asio
and fmt
(skip the first one for now, cause it is a more complicated story). They are not up to date on nix packages, so I can't simply get it from there.
But I realized that it is basically another nix file, which should be rather possible to embed in my project, so de dependency will be build before.
I've tried to embed it into the default.nix
file but it doesn't work that way.
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";
}
How to install latest/desired version of the package?
How to combine multiple derivations and rely on them?
Upvotes: 1
Views: 1095
Reputation: 7359
Short answer: you need to use a let binding. (Long answer: use separate file + callPackage
, see below)
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
I'd recommend to copy the whole file, to keep things readable.
Packages in Nixpkgs are typically described in files that aren't themselves buildable expressions (ie returning a derivation) but functions from packages to a derivation. So essentially you need to apply the function with the package set, but instead of normal function application, we use the pkgs.callPackage
function, which takes care of reflecting on the arguments so you don't have to use { x, ... }:
syntax and adding the override
attribute.
It also allows overriding packages and passing extra arguments via the second argument.
pkgs.callPackage ./fmt.nix {}
or in your case just callPackage
because you've used the with
keyword on what could otherwise be called pkgs
(let pkgs = import <nixpkgs> {}; in
).
I usually recommend to avoid the with
keyword because it needlessly complicates Nix's scope rules and it can make finding bindings harder for us humans who don't have a Nix evaluator plugged into our brains.
Upvotes: 3