stdenv.mkDerivation and sh: /usr/bin/env: not found

I am creating a derivation for a very simple package. The default.nix:

{ stdenv, fetchFromGitHub, pandoc, cgreen }:

stdenv.mkDerivation rec {
  pname = "uint128";
  version = "20200902";

  src = fetchFromGitHub {
    owner = "mkgvt";
    repo = "uint128";
    rev = "master";
    sha256 = "0b3p8qka7yqq8km754k2dimjg9pxaf9mlnnzmvajvfw8xg6mh13k";
  };

  buildInputs = [
    cgreen
    pandoc
  ];

  enableParallelBuilding = true;

  doChecks = true;
  checkTarget = "tests";

  meta = with stdenv.lib; {
    description = "A C library supporting operations on 128-bit unsigned integers";
    homepage = "https://github.com/mkgvt/uint128/";
    license = licenses.lgpl3;
    platforms = platforms.unix;
    maintainers = with maintainers; [ mkg ];
  };
}

The overlay ~/.config/nixpkgs/config.nix that makes it available:

let
  sources = import ./nix/sources.nix;
  pkgs = import sources.nixpkgs {};
in {
  allowUnfree = true;
  packageOverrides = pkgs: {
    cgreen = pkgs.callPackage ./packages/cgreen {};
    uint128 = pkgs.callPackage ./packages/uint128 {};
  };
}

But when I attempt to build the package from ~/.config/nixpkgs/packages/uint128:

$ nix-build -E 'with import <nixpkgs> {}; callPackage ./default.nix {}'
these derivations will be built:
  /nix/store/pk6y1zb4bgfwm6iaax6pr54s4hh1dgx0-uint128-20200902.drv
building '/nix/store/pk6y1zb4bgfwm6iaax6pr54s4hh1dgx0-uint128-20200902.drv'...
unpacking sources
unpacking source archive /nix/store/dlb3x8cw1pr9lwh2j2f7z6z5wk36cczy-source
source root is source
patching sources
configuring
no configure script, doing nothing
building
build flags: -j4 -l4 SHELL=/nix/store/9ywr69qi622lrmx5nn88gk8jpmihy0dz-bash-4.4-p23/bin/bash
gcc -MM -MF uint128_tests.d uint128_tests.c
pandoc -o LICENSE.html LICENSE.md
pandoc -o README.html README.md
gcc -fPIC -I. -Wall -Wpedantic -Wextra -c uint128_tests.c uint128.h
gcc -shared -o uint128_tests.so uint128_tests.o -lcgreen
sh: /usr/bin/env: not found
No tests found in 'uint128_tests.so'.
make: *** [Makefile:36: tests] Error 1
make: *** Waiting for unfinished jobs....
builder for '/nix/store/pk6y1zb4bgfwm6iaax6pr54s4hh1dgx0-uint128-20200902.drv' failed with exit code 2
error: build of '/nix/store/pk6y1zb4bgfwm6iaax6pr54s4hh1dgx0-uint128-20200902.drv' failed

Running the tests from within a pure environment works fine:

$ nix-shell --pure
$ make tests
gcc -MM -MF uint128_tests.d uint128_tests.c
gcc -fPIC -I. -Wall -Wpedantic -Wextra -c uint128_tests.c uint128.h
gcc -shared -o uint128_tests.so uint128_tests.o -lcgreen
Running "uint128_tests" (9 tests)...
  "uint128_tests": 16 passes in 2ms.
Completed "uint128_tests": 16 passes in 2ms.

using this shell.nix:

let
  pkgs = import <nixpkgs> {};
in
with pkgs;
mkShell {
  buildInputs = [
    cgreen
    pandoc
  ];
}

Note: the package for cgreen is very similar and builds fine:

{ stdenv, fetchFromGitHub, cmake, asciidoctor }:

stdenv.mkDerivation rec {
  pname = "cgreen";
  version = "1.3.0";

  src = fetchFromGitHub {
    owner = "cgreen-devs";
    repo = "cgreen";
    rev = version;
    sha256 = "07qgxcfb73dmgcxglxjxk1lj5zdb1x5wi022hr1hivj5psm6pvhr";
  };

  buildInputs = [
    cmake
    asciidoctor
  ];

  enableParallelBuilding = true;
  patches = [ ./patch.nm-path ];

  doChecks = true;
  checkTarget = "tests";

  meta = with stdenv.lib; {
    description = "A C & C++ unit tester and mock framework with a taste of BDD";
    homepage = "https://cgreen-devs.github.io/";
    license = licenses.isc;
    platforms = platforms.unix;
    maintainers = with maintainers; [ mkg ];
  };
}

To summarize, even though cgreen and uint128 package have very similar default.nix files and are both accessed through an overlay, the uint128 package can’t find /usr/bin/env and fails while the former does not fail. What am I doing wrong?

NIx builds packages in sandbox, which intentionally does not have /usr/bin/env.

Looking at the Makefile, I would guess the issue comes from cgreen-runner (try disabling uint128 tests to see if the tests are indeed responsible, or maybe use makeFlags = ["-n"] and disable parallel building).

If that is the source, you will need to find where it is called and patch it out. If it appears in a shebang of an executable file in $out/bin, the generic builder can patch it out for you but you need the program that would be executed by env on PATH in the build of the derivation containing the executable.

1 Like

Thanks @jtoljnar. That was the hint that I needed.

cgreen-runner references /usr/bin/nm internally, which gets rewritten to be /user/bin/env nm when the cgreen package is created. So /usr/bin/env doesn’t appear anywhere in the source for either uint128 or cgreen. Disabling tests in default.nix didn’t solve the problem because the all target in the Makefile was explicitly calling the tests rule. Removing that keeps cgreen-runner from being called and solves the problem.

Incidentally, there was another problem in creating the package for uint128. I needed to specify an installPhase which copies uint128.h (and documentation) to the output directory. Once I did that, the package now builds and can be installed.

Thanks for your help.