Suppose have a folder, and inside the folder there is a default.nix
file that returns the result of mkDerivation
.
As an example, I recently learned how to make a nix derivation containing Node.js: Managing multiple versions of Node.js with nix? - #9 by trusktr
I can run nix-build
from inside the folder that contains that default.nix
, and it outputs result
that is symlinked to the output folder in the nix store. The derivation contains a /bin/node
which I can manually run fine.
I haven’t successfully “packaged” it yet, as I haven’t actually installed it to the system or used it in a nix-shell yet. Being able to run ./result/bin/node
has been enough to get me back to work on local projects.
To take things further, how would I
- run it with the
node
executable available in a nix-shell
?
-
import
it in another derivation directly from the local folder that contains this default.nix
?
- Is it even possible to import from a local directory to begin with?
- install it to my system with
nix-env
?
- I imagine that if what I ask in question
2.
is possible, then another way to install it to my system is by importing it in my configuration.nix
file and perhaps adding it to environment.systemPackages
.
6 Likes
It sounds like what you might want here is an overlay to extend pkgs
. Here’s a simple one that lives in my ~/.config/nixpkgs/overlays
that adds a few packages to my system. I can then install these through home.packages
(I use home-manager) as I normally would. Works auto-magically.
The motivation for this overlay was similar to what it sounds like you’re driving at: There was a package (kepubify
in my case) that I couldn’t get through one of the official channels that I wanted to use in a derivation. Creating an overlay that extended pkgs
to include that application let me work with it like I would any other NixOS package.
I’m still learning Nix/NixOS myself, and have wrestled with how to use overlays system-wide. Right now I have a /etc/nixos/overlays
folder that contains an additional kernel module my laptop needs. Unlike ~/.config/nixpkgs/overlays
, that overlay doesn’t get picked up automatically. Right now I’m importing it with
nixpkgs.overlays = [ (import ./overlays) ];
in my /etc/nixos/configuration.nix
, but I feel like there must be a better way.
3 Likes
You could go the overlay way as described by necopinus or a somewhat simpler version that I use in my configuration.nix. Here’s a (shortened) version:
environment.systemPackages = with pkgs; [
...
which
wireshark
xscreensaver
zip
(callPackage ./pkgs/go-for-it { })
(callPackage ./pkgs/nixos-shell { })
(writeShellScriptBin "afuse-sshfs" ''
mkdir -p $HOME/sshfs
exec ${afuse}/bin/afuse -o mount_template='${sshfsFuse}/bin/sshfs %r:/ %m' -o unmount_template='fusermount -u -z %m' $HOME/sshfs
'')
] ;
./pkgs/nixos-shell/default.nix is a common package that looks like this:
{ stdenv, fetchFromGitHub, bash }:
stdenv.mkDerivation rec {
name = "nixos-shell-${version}";
version = "b0c0d93c0db4ce5661d0f2e6cbea4d554f9c28de";
src = fetchFromGitHub {
owner = "Mic92";
repo = "nixos-shell";
rev = "${version}";
sha256 = "0z2mklcdrf98mm5ywvp4n3y7rdbizjz6wnqzj6c28r0cy1an5xib";
};
patches = [ ./nixos-shell.patch ];
buildInputs = [ bash ];
preConfigure = ''
export PREFIX=$out
'';
}
As you see, I’m also using writeScriptBin directly for very simple scripts that don’t warrant a full package.
Both callPackage and writeShellScriptBin are in the pkgs scope, so you can also refer to them as pkgs.callPackage and pkgs.writeShellScriptBin.
The downside of not using an overlay is that other packages cannot depend on them, unless you include them in that other package through callPackage as well.
2 Likes
Hi,
No need for an overlay, nor touching your NixOS config.
Nix can handle any files containing any Nix expressions.
Once you have an “usual” (a function) default.nix file, you can “instantiate” (see note) it with e.g:
pkgs.callPackage ./default.nix {}
This Nix expression is the result of mkDerivation
(which is a derivation) and can be used where a “package” is expected, for instance in mkShell
’s inputsFrom
or nix-build
or whatever.
More specifically, consider those files:
{ writeShellScriptBin }:
# This is eventually evaluated as mkDerivation, thus derivation
writeShellScriptBin "somebin" ''
echo it works
''
{ pkgs ? import <nixpkgs> {} }:
pkgs.callPackage ./derivation.nix {}
{ pkgs ? import <nixpkgs> {} }:
pkgs.mkShell {
buildInputs = [ (pkgs.callPackage ./derivation.nix {}) ];
}
Note that the “usual” package file is in derivation.nix
because default.nix
has a special meaning to nix-build
.
You can then:
- run it with the executable available in a
nix-shell
: $ nix-shell
-
import
it in another derivation: you already did it in shell.nix
and default.nix
possible in NixOS configuration.nix
as well, of course
- install it:
$ nix-env -if .
(or $ nix-env -if default.nix
as usual)
- as usual, build it:
$ nix-build
for a result
symlink
The file naming is what I found more convenient as it does not require specifying the file name for nix-shell
and nix-build
, but you do as you want. There’s really, IMHO, only those 2 (default) rules in Nix ;).
Note: this is not the proper word. It’s actually a function application, with a bit of “magic” (introspection) from callPackage
.
4 Likes