KAction
KAction

Reputation: 625

Nix does not trigger rebuild of coreutils

I am running Nix on top of Devuan GNU/Linux system (x86_64), with following ~/.nixpkgs/config.nix, as documented in Nix Pills:

{
  packageOverrides = pkgs: {
    coreutils = pkgs.coreutils.override {
      aclSupport = false;
      attrSupport = false;
      selinuxSupport = false;
    };
    coreutils2 = pkgs.coreutils.override {
      aclSupport = false;
      attrSupport = false;
      selinuxSupport = false;
    };
    w3m = pkgs.w3m.override {
      graphicsSupport = false;
      imlib2 = null;
      x11Support = false;
      mouseSupport = true;
    };
  };
}

But when I run nix-env -iA nixpkgs.coreutils, Nix installs stock version of coreutils, with optional features enabled:

$ nix-env -iA nixpkgs.coreutils
replacing old 'coreutils-8.31'
installing 'coreutils-8.31'
$ ldd /home/iu/.nix-profile/bin/ls |grep libattr
        libattr.so.1 => /nix/store/5xwmn6ai8c42j84k6gdzja0lnkdi3c60-attr-2.4.48/lib/libattr.so.1
(0x00007f0354e7f000)

But if I refer to same derivation (referential transparency) via other name:

$ nix-env -iA nixpkgs.coreutils2

Nix starts rebuild from source, which results in binaries, compiled without optional features, just as requested. What is even more mysterious, overriding build options for w3m works and do trigger rebuild.

Also, I noticed same strange behavior with gnutar. Is is somehow related to the fact that coreutils and gnutar are essential to Nix itself? How can I make coreutils in expected way?

Upvotes: 1

Views: 399

Answers (1)

Robert Hensing
Robert Hensing

Reputation: 7369

This happens because one final overlay is applied after your overlays. (You're using packageOverrides which becomes essentially the first user overlay)

To quote the commit:

The stdenvOverrides overlay is used to bring packages forward during bootstrapping via stdenv.overrides. These packages have already had the overlays applied to them in the previous boostrapping stage. If stdenvOverrides is not last in the overlays stack, all remaining overlays will windup being applied again to these packages.

gnutar is also set by this overlay.

$ nix repl '<nixpkgs>'
nix-repl> lib.attrNames (stdenv.overrides pkgs pkgs)
[ "acl" "attr" "bash" "binutils" "binutils-unwrapped" "bzip2" "coreutils" "diffutils" "findutils" "gawk" "gcc" "glibc" "gnugrep" "gnumake" "gnupatch" "gnused" "gnutar" "gzip" "patchelf" "pcre" "xz" "zlib" ]

The "good" news is you can use a normal overlay to configure the last overlay. It's convoluted but it works:

nix-repl> (import <nixpkgs> { overlays = [ (self: super: { stdenv = super.stdenv // { overrides = self2: super2: super.stdenv.overrides self2 super2 // { coreutils = "put your coreutils here"; }; }; }) ]; }).coreutils
"put your coreutils here"

I recommend using overlays instead of packageOverrides to make sure this happens in the last "user" overlay. So your overlay would be similar to:

_: super:
let
  coreutils = pkgs.coreutils.override {
    aclSupport = false;
    attrSupport = false;
    selinuxSupport = false;
  };
in
{
  # Overrides for stuff from stdenv go here. They're applied last
  # so we use the same stdenv for builds but a custom coreutils etc for
  # our system. This allows use to still use cache.nixos.org.
  stdenv = super.stdenv // {
    overrides = self2: super2: super.stdenv.overrides self2 super2 // {
      inherit coreutils;
    };
  };

  w3m = ...;
}

Upvotes: 2

Related Questions