Generic builder: minimal autoconf example?

I’m putting together a presentation on Nix. My first example consists of a simple C program and accompanying Nix expression using derivation and a standalone builder script.

For my second example, I’d like to demonstrate mkDerivation and it’s generic builder (eliminating the need for the builder script). I thought I could get away with simply providing my project with a Makefile, but it seems this is not enough, and that the generic builder requires a configure script and possibly some more autotools packaging.

I’m comfortable writing Makefiles, but not familiar with Autotools, and in particular, not sure how to correctly specify the install destination (DESTDIR, prefix, bindir). My example C program involves an optional preprocessor #define as well.

The program source, simple.c:

#include <stdio.h>

#ifndef NUM
#define NUM 1
#endif

void main() {
  printf("Simple! %d\n", NUM);
}

My current Makefile (which I guess I need to translate to a Makefile.am?).

prefix = /
bindir = $(prefix)bin

NUM := 1
CPPFLAGS += -DNUM=$(NUM)

all: simple

install:
	install -D -m755 simple $(DESTDIR)$(bindir)/simple

clean:
	rm -f simple

.PHONY: all, install, clean

Finally, the Nix expression:

{ stdenv, fetchurl, num }:

stdenv.mkDerivation rec {
  name = "simple-${version}";
  version = "0.1";

  src = fetchurl {
    url = "https://github.com/ivanbrennan/simple/archive/e351e9649b1cbe6956593f6226f74f1123a8e1d9.tar.gz";
    sha256 = "18z51nqhsfb8n1bhxs0cqnxhhx8dcp2j37i8jq7z84spniwi4fjr";
  };

  buildFlags = [ "NUM=${toString num}" ];
}

When I try to build with nix-build:

nix-build /path/to/default.nix \
    --arg stdenv   '(import <nixpkgs> {}).stdenv' \
    --arg fetchurl '(import <nixpkgs> {}).fetchurl' \
    --arg num       0

it tries to install into /bin, which of course fails:

configuring
no configure script, doing nothing
...
install -D -m755 simple /bin/simple
install: cannot create regular file '/bin/simple': Permission denied

I thought the configurePhase would set prefix to $out. This is what got me thinking I need to provide my project with some autotools packaging, at least a configure script.

Now I’m reading up on autotools, which I can see is a large topic. I’m curious what the minimal requirements would be to get my project working with mkDerivation and the generic builder. Any help is much appreciated.

Yeah, stdenv.mkDerivation doesn’t pass prefix to Make. But you can easily do that:

makeFlags = [ "prefix=$(out)" ];

or in Nix >= 2.0:

makeFlags = [ "prefix=${placeholder "out"}" ];

(The latter is better because it doesn’t rely on variable expansion in Make.)

I would avoid using Autotools if possible.

3 Likes

Ah, great – that works. Thanks so much!