Building and installing a C project with Nix

Today I learned how to build and install a simple C project on Nix(OS).

After some reading on the Internet πŸ“š, I finally understood the basics of building and installing a package from C sources using a Nix expression file (the .nix file in the following examples).

#packaging #coding #nix #diary #c

The expression file uses the standard build environment 🧰. Essentially, this environment abstracts the traditional Makefile based build proces (i.e., make && make install).

For learning purposes, I decided to package my hobby project, the text-based journaling program diary πŸ““.

Writing the Nix expression file

I built the expression file based on a an example from the Nix book.

The Nix expression file diary.nix to install the stable version of the diary program fetches the source by tag from the Git repository:

let
  pkgs = import <nixpkgs> { };
in
  pkgs.stdenv.mkDerivation {
    name = "diary";
    version = "v0.10";
    buildInputs = with pkgs; [
      ncurses
      curlFull
      lttng-ust
    ];

    src = pkgs.fetchgit {
      url = "https://git.in0rdr.ch/diary.git";
      rev = "refs/tags/v0.10";
      hash = "sha256-jDPfqUjf0ZETYqPxvEJ2/YFFjNsF7yvVQiThc5yMvjc=";
    };

    installPhase = ''
      install -d $out/bin
      install -d $out/share/man/man1
      install -m755 diary $out/bin/
      install -m644 man1/diary.1 $out/share/man/man1/
    '';
  }

The mkDerivation call does most of the work. There we define the package name and version, as well all of the dependencies required to build the project. In this case, the diary program depends on the curl and ncurses libraries as well as the lttng tracing library.

The source code src can be fetched conveniently from Git (using the fetchgit β€œbuilder”) or from other remote sources (see related β€œfetch” builtin functions).

To build a nightly release from the master branch, I only had to slightly tune the src of the unstable Nix expression:

    src = pkgs.fetchgit {
      url = "https://git.in0rdr.ch/diary.git";
      hash = "sha256-laKIVxfqJqBkB2d0F8tOOnpAXXRzHFfpjhAzZT8MX8k=";
    };

The sha256 hash can be obtained using nix-prefetch-git:

# get hash for the specific tag/release
nix-prefetch-git https://git.in0rdr.ch/diary.git --rev refs/tags/v0.10

# get hash for latest nightly build from master branch
nix-prefetch-git https://git.in0rdr.ch/diary.git

Finally, the installPhase needed a bit of tuning and has a small difference to what is commonly used in a Makefile on a traditional Linux distribution. But that was not too hard either, I simply had to translate my install target from the already existing Makefile.

The install target:

install: $(TARGET)
        install -m755 $(TARGET) $(BINDIR)/$(TARGET)
        install -d $(MANDIR)/man1
        install -m644 $(MAN1) $(MANDIR)/$(MAN1)

The corresponding Nix installPhase:

      install -d $out/bin
      install -d $out/share/man/man1
      install -m755 diary $out/bin/
      install -m644 man1/diary.1 $out/share/man/man1/

Very similar indeed. One point to note here is that the fixup phase will automatically install the man pages to the correct location.

Building and installing the C project

Once the expression file is written, building and installing the program is a peace of cake 🍰:

# Build stable package
nix-build nix/diary.nix

# Build latest nightly version
nix-build nix/diary-unstable.nix

To install the package from the expression file to the user environment:

# Install stable package
nix-env -i -f nix/diary.nix

# Install latest nightly version
nix-env -i -f nix/diary-unstable.nix

You can even verify the location of the man page by using manpath -q or query the installed package with nix-env -q.

Next steps

Now that we have drafted the basic expression file, we might also add it to the nixpkgs repository on GitHub. I haven't checked the contributor requirements in detail yet. Hit me up on IRC #p0c or on Mastodon if you want to contribute to the discussion or have some inputs for me (yes, I still consider my self a Nix noobie πŸ˜„).

πŸ›œ RSS | 🐘 Mastodon | πŸ’¬ IRC