Build my first package

In the section, we create a nix derivation for installing netCDF package

Create the derivation script

First we need to create the default.nix as below:

{
# pkgs ? import (fetchTarball https://channels.nixos.org/nixpkgs-22.05-darwin/nixexprs.tar.xz) {} # use default
pkgs ? import <nixpkgs> {} # use default
}:

with pkgs;

let
   packages = rec {
      nc = pkgs.stdenv.mkDerivation rec {
            pname = "netcdf-c";
            version = "3.9-test";

            src = pkgs.fetchurl {
               url = "https://downloads.unidata.ucar.edu/netcdf-c/4.9.0/netcdf-c-4.9.0.tar.gz";
               sha256 = "sha256-TJVgIrecCOXhTu6N9RsTwo5hIcK35/qtwhs3WUlAC0k=";
            };

            buildInputs = [
               pkgs.cmake
               pkgs.gcc
               pkgs.m4
               pkgs.zlib
            ];

            configurePhase = ''
               ./configure --disable-netcdf4 --disable-hdf5 --prefix /tmp/tmp/netcdf-install
            '';

            buildPhase = ''
               make
            '';

            installPhase = ''
               make install
               mkdir -p $out
               mv /tmp/tmp/netcdf-install/* $out
            '';
            shellHook = ''
               LD_LIBRARY_PATH=$out/lib:$LD_LIBRARY_PATH
               PATH=$out/bin:$PATH
            '';
   };
   # The shell of our experiment runtime environment
      expEnv = mkShell rec {
         name = "exp01Env";
         buildInputs = [nc];
      };
   };
in
   packages

This file looks similar to the one discussed in previous section, but its structure changed a little. The main difference is that:

the file does not return a single derivation (the chord package) but a set with several attributes:

  • nc: where the actual package to be installed

  • expEnv: shell environment to be used to run the experiment

Note

the structure for the .nix is:

{pkgs ? import ....}:

with pkgs;
  let
      packages = rec {

          pkg1 = pkgs.stdenv.mkDerivation rec { ... };
          pkg2 = ....
          ....
          env1 = mkShell rec { ... };
          env2 = ...
          ....
      };
in
  packages

Build the package

We can use both nix-shell or nix-build for the above file, while we need to tell the command on which attribute to be used (e.g., whether it is nc or expEnv)

nix-build default.nix -A nc

We will see all the binaries and libraries are built in ./result, which is linked to the nix store (e.g., /nix/store/xxlf2ndmajaadbcrlgj0nfcj023vhg5a-netcdf-c-3.9-test).

Run the package

Option 1: run the package manually within the shell

After the build (last step), we can run netCDF within the environment of expEnv

nix-shell default2.nix -A expEnv

After this we can test ncdump within the nix shell (e.g., ncdump --help)

Option 2: run the package with command

We can define a script (e.g., for using ncdump) so we don’t have to manually get into the nix shell. For example, the script (e.g., test.sh) can be something like

#!/usr/bin/env bash
ncdump --help

Then we can execute test.sh within the nix-shell as:

nix-shell default.nix -A expEnv --command ./test.sh

Option 3: define the command with the derivation script

We can define the runtime script within the nix derivation shell, so everytime we don’t even need to attach --command. In order to do so, we need to add shellHook under mkShell rec. For example,

expEnv = mkShell rec {
    name = "exp01Env";
    buildInputs = [nc];
    shellHook = "./test.sh";
};

Then we can execute test.sh simply by

nix-shell default.nix -A expEnv

Option 4: nix-shell shebang

We even don’t have to call nix-shell even we need to use nix package or environment. In order to do so, we can use shebang. For example, we can have a shebang script (e.g., test_shebang.sh) as:

#!/usr/bin/env nix-shell
#!nix-shell default3.nix -A expEnv -i bash
ncdump --help

Then we can execute the test_shebang.sh as;

./test_shebang.sh