A Practical Nix Reference
2020-08-10Table of Contents
I have trouble remembering the exact syntax needed to do stuff in nix. Here's a little reference on how to do those things (WITH A STRONG FOCUS ON PYTHON).
Making a shell
This is the base for a nix-shell file.
let pkgs = import <nixpkgs> {};
in
pkgs.mkShell rec {
name = "SOME SHELL NAME";
buildInputs = [];
}
With python...
Just add the expression
(pkgs.python3.withPackages (ps: with ps; [PYTHON PACKAGES HERE]))
into the buildInputs
list in mkShell.
Creating a nix derivation for a python package
The file is a function which creates a python package derivation.
{buildPythonPackage, *other libraries required to build the package, eg. numpy, matplotlib...*}:
buildPythonPackage rec {
pname = "MYPACKAGENAME";
version = "0.IDUNNO.1";
src = *WHATEVER THE SOURCE IS*;
# Inputs required to run the tests
checkInputs = [];
# Compile-time input requirements
nativeBuildInputs = [];
buildInputs = [];
# Run-time input requirements eg. scipy needs numpy in the propagatedBuildInputs to run
propagatedBuildInputs = [];
# Bool for whether to run tests
doCheck = true;
meta = {
description = "Some description for the package";
homepage = "www.somewebsite.com";
};
}
Pypi source
If you're taking the source from Pypi add the function fetchPypi
to the function arguments and set the src
variable to:
src = fetchPypi {
inherit pname version;
sha256 = "the sha256 value from the pypi package page";
}
Github source
If the source is in a git repo, use the builtins.fetchGit
function:
src = builtins.fetchGit {
url = "the git url";
rev = "the commit revision";
# ref allows you to fetch from a branch
ref = "my-branch";
};
Local source
If it's a local source, just use the file (without string quotes):
src = ./my_file_src
If it's compressed or something, nix can handle that too.
Adding the derivation as an overlay
If you don't want to have these derivations in individual projects, they can be added into your <nixpkgs>
with an overlay. I like to have the derivations inside the folder ~/.config/nixpkgs/pkgs/
, and you should put your overlays in the folder ~/.config/nixpkgs/overlays/
. Every overlay you add in that folder is automatically applied to your available <nixpkgs>
.
An example overlay to add a python package is:
self: super:
{
python3 = super.python3.override {
packageOverrides = python-self: python-super: {
new_python_package = super.callPackage ../pkgs/new_python_package.nix { };
};
};
}
Then new_python_package
will be available in the python3Packages
.
This is using the pkgs.callPackage
function to fill in the derivation arguments. There's a nix pill on how this function works here. It just takes the intersection between all of the package repository's derivations and the arguments and then fills in the arguments with this.
Adding a local package to your nix-shell
Just use the pkgs.callPackage
function to load the locally defined package like this:
let
pkgs = import <nixpkgs> {};
test_package = pkgs.callPackage ./test_package.nix { };
in pkgs.mkShell rec {
name = "Cool guy shell";
buildInputs = [test_package];
}
If the imported package contains a python package that uses buildPythonPackage
and some other stuff, they probably won't be in scope at the <nixpkgs>.callPackage
function. Luckily there's a python specific scope in the <nixpkgs>.python3Packages.callPackage
version. There's a few different callPackage
s like this that you can use.