nix report
This article is created as a record of the feedback of the usage of nix, also stand for learning how to use nix in daily developing life. Remember I would not dig into the implementation or model concept inside of nix but all about how to use it to improve the developing environment.
1. Install
To install nix all you have to do is running:
sh <(curl https://nixos.org/nix/install) --no-daemon and follow the
content, provided by the script after the script installed process down,
on Linux or macOS.
To avoid outdated information, here is the single-user installation(which you do above), and the multi-user installation.
2. Introduction
After installation, you would get several different commands for different purposes. I would introduce them one by one(only for those I'm using).
2.1. nix-env
nix-env is like brew for MacOS, apt-get for Ubuntu, yum for
CentOS, but for all platform with nix. This command is the first one
command would help immediately. You can do: nix-env -i go or
nix-env --install go, after that let's check the binary go by
which go, is located at $HOME/.nix-profile/bin/go. You can also use
different channel(package source) for self-deployed packages or any
other is not provided by nix channel.
Use nix-env --help to get more information
2.2. nix-shell
nix-shell would read shell.nix or fallback to read default.nix
these config files. To understand what we do in it we need an example:
let
pkgs = import <nixpkgs> { };
inherit (pkgs) mkShell;
inherit (pkgs) haskellPackages;
inherit (haskellPackages) cabal-install;
inherit (haskellPackages) stylish-haskell;
ghc = haskellPackages.ghcWithPackages (pkgs: with pkgs; [base mtl]);
in
mkShell {
buildInputs = [
ghc
cabal-install
stylish-haskell
];
}
mkShell would return a shell by its argument set: {}, at here we can
take a look at stylish-haskell this Haskell formatter, in nix-shell
environment type which stylish-haskell would get
/nix/store/qqj9ldclapfbxhnvb357mjy5d5rjg6ip-stylish-haskell-0.9.2.2/bin/stylish-haskell,
and if you quit the environment should won't have the binary.
2.3. nix-build
Now, we already introduce the global level installer and project level installer. We have to go into how to create your own package.
nix-build would read default.nix to use its value as your package.
Let's take a look at what it means.
let
pkgs = import <nixpkgs> { };
dependencies = import ./deps.nix;
in
pkgs.haskellPackages.callPackage ./little-scheme.nix { dependencies=dependencies; }
Ignore deps.nix, that's a list has all Haskell dependencies I used.
pkgs.haskellPackages.callPackage creates a haskell package via it's
argument. Let's dig into what little-scheme.nix do:
{ mkDerivation, base, mtl, dependencies, stdenv }:
mkDerivation {
pname = "little-scheme";
version = "0.1.0";
src = stdenv.lib.sourceFilesBySuffices ./. [".hs" ".cabal" "LICENSE"];
isLibrary = false;
isExecutable = true;
executableHaskellDepends = [ base mtl ] ++ dependencies;
license = stdenv.lib.licenses.mit;
}
src be set to
stdenv.lib.sourceFilesBySuffices ./. [".hs" ".cabal" "LICENSE"], this
line means only .hs, .cabal and LICENSE would lead a new build.
executableHaskellDepends would take a list of Haskell libraries.
{}: expression is a function. {} use pattern matching to extract the
value from input set. a: c is take a return c, a: b: c is take
a return b: c, consider to read
lambda calculus to
understand the function in nix.
3. Advanced use case
3.1. direnv
direnv is a powerful shell environment extension, it loads or unloads
an environment depending on the current directory. To install it we can
execute nix-env --install direnv, then add eval "$(direnv hook zsh)"
at the end of
=$HOME/.zshrc=(for
others shells).
direnv supports using nix as environment configuration, you can put
use_nix in the $dir/.envrc, and it would watch $dir/shell.nix and
$dir/default.nix to update the environment. However, the current
version use_nix has cache missing issue, so you can just copy whole
content from
https://github.com/kalbasit/nur-packages/blob/master/pkgs/nixify/envrc,
and put use_nix -s shell.nix in the $dir/.envrc.
p.s. A minor issue is direnv do not work with alias, so probably
still have to use $HOME/.zshrc to manage them.