问题
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?
回答1:
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 = ...;
}
来源:https://stackoverflow.com/questions/58758367/nix-does-not-trigger-rebuild-of-coreutils