Search code examples
nix

nix: override doCheck in pybind11


Looking at: https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/libraries/pybind11/default.nix, it seemed to me that I should be able to avoid running tests (i.e., set -DPYBIND11_TEST=OFF) with something like the following:

pybind11 = pkgs.pybind11.overrideAttrs (oldAttrs: rec {
   doCheck = false;
});

This, however, does not work.

I solved my problem by modifying cmakeFlags directly:

  pybind11 = pkgs.pybind11.overrideAttrs (oldAttrs: rec {
      cmakeFlags = [
        "-DPYTHON_EXECUTABLE=${pkgs.python.interpreter}"
        "-DPYBIND11_TEST=OFF"
      ];
  });

But I was wondering why the former approach does not work.


Solution

  • It doesn't work because the derivation is using the rec keyword, which doesn't have a concept of overriding. An extract:

    { stdenv, fetchurl, fetchFromGitHub, cmake, catch, python, eigen }:
    
    stdenv.mkDerivation rec { #0
      name = "pybind-${version}";
      version = "2.2.4";
    
      doCheck = true; #1
    
      cmakeFlags = [ 
        "-DPYBIND11_TEST=${if doCheck then "ON" else "OFF"}"
      ];
    }
    

    With .overrideAttrs (oldAttrs: { doCheck = false; }) you only override the doCheck attribute, but not the cmakeFlags, which still references the doCheck (#1) from the lexical scope introduced by the rec {} (#0)

    So the following is equivalent to the snippet above:

    { stdenv, fetchurl, fetchFromGitHub, cmake, catch, python, eigen }:
    
    stdenv.mkDerivation (let #0
      name = "pybind-${version}";
      version = "2.2.4";
    
      doCheck = true; #1
    
      cmakeFlags = [ 
        "-DPYBIND11_TEST=${if doCheck then "ON" else "OFF"}"
      ];
    in { #0
      name = name;
      version = version;
      doCheck = doCheck; #1
      cmakeFlags = cmakeFlags;
    }
    

    mkDerivation can only see the attrset it gets, but can not introspect and modify the expression that builds that attrset. This a necessary Nix language design principle because it lets you reason about the code and enables laziness. The rec semantics are simply not suitable for overriding.