-
-
Notifications
You must be signed in to change notification settings - Fork 14.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix replaceStdenv evaluation: avoid infinite recursion #144747
base: staging
Are you sure you want to change the base?
Conversation
Unfortunately coreutils requires automake. |
6574886
to
f044a50
Compare
|
f044a50
to
7f362b9
Compare
This pull request has been mentioned on NixOS Discourse. There might be relevant details there: |
70bacf6
to
82e35f5
Compare
This PR has been updated and rebased on top of master where perl now depends on zlib causing one circular dependency (introduced by #167084). |
I cannot reproduce, can you post a (minimal) example? |
Here is an example called import ./. {
config = {
replaceStdenv = { pkgs }: let
# Bootstrap a new stdenv that includes our nss_sss in glibc
glibc = pkgs.glibc.overrideDerivation (old: {
postInstall = old.postInstall + ''
ln -s ${pkgs.nss_sss}/lib/*.so.* $out/lib
'';
});
binutils = pkgs.binutils.override {
libc = glibc;
};
gcc = pkgs.gcc.override {
bintools = binutils;
libc = glibc;
};
in
builtins.trace "Enabling Custom Stdenv" pkgs.stdenv.override {
cc = gcc;
overrides = self: super: {
inherit glibc binutils gcc;
};
allowedRequisites = pkgs.stdenv.allowedRequisites ++
[ glibc.out glibc.dev glibc.bin binutils pkgs.nss_sss ];
};
};
overlays = [
(final: prev: {
nss_sss = prev.callPackage (
{ stdenv
, fetchurl
, pkgconfig
, glibc, pam, openldap, kerberos, dnsutils, cyrus_sasl, nss
, popt, talloc, tdb, tevent, ldb, ding-libs, pcre, c-ares
, glib, dbus
}:
let
version = "1.16.5";
in
stdenv.mkDerivation rec {
name = "sssd-nss-client-${version}";
src = fetchurl {
url = "https://fedorahosted.org/released/sssd/sssd-${version}.tar.gz";
sha256 = "0ngr7cgimyjc6flqkm7psxagp1m4jlzpqkn28pliifbmdg6i5ckb";
};
# libnss_sss.so does not in fact use any of these -- they're just needed for configure
nativeBuildInputs = [ pkgconfig
pam openldap kerberos dnsutils cyrus_sasl nss
popt talloc tdb tevent ldb ding-libs pcre c-ares
glib dbus
];
configureFlags = [
# connect and use to system sssd:
"--localstatedir=/var"
"--sysconfdir=/etc"
"--with-os=redhat"
"--with-nscd=${glibc.bin}/sbin/nscd"
"--with-ldb-lib-dir=$(out)/modules/ldb"
"--disable-cifs-idmap-plugin"
"--without-autofs"
"--without-kcm"
"--without-libnl"
"--without-libwbclient"
"--without-manpages"
"--without-nfsv4-idmapd-plugin"
"--without-python2-bindings"
"--without-python3-bindings"
"--without-samba"
"--without-secrets"
"--without-selinux"
"--without-semanage"
"--without-ssh"
"--without-sudo"
];
enableParallelBuilding = true;
buildFlags = [ "libnss_sss.la" ];
installTargets = [ "install-nsslibLTLIBRARIES" ];
} ) {};
})
];
} And try with |
I'm not really sure about this, hopefully someone else can weigh in. I tried to make a more minimal example like this:
and building with I'm assuming that you can resolve the infinite recursion inside your own built stdenv rather than have to rely on the changes you made. But I might be totally off here. |
All of those tests (even with ccacheStdenv) are too minimal and don't trigger the infinite recursion as they don't modify the
If you could find a way to do it with my reproducer, I would be happy to study your solution 🤗 |
I haven't really had the time to make a better/smaller reproducer, but I seem to remember some eval issues when applying this, so I think we shouldn't merge this as-is. |
Which eval issues are you refering since all the checks have passed? BTW what about this smaller reproducer: { useFix ? false }:
let
nixpkgs = if useFix then
(builtins.fetchGit {
url = "https://github.com/dguibert/nixpkgs";
ref = "refs/heads/dg/fix-replacestdenv-coreutils";
})
else
(builtins.fetchGit {
url = "https://github.com/NixOS/nixpkgs";
ref = "refs/heads/staging";
});
in
import nixpkgs {
config = {
replaceStdenv = { pkgs }: let
# Bootstrap a new stdenv that includes a modified glibc
glibc = pkgs.glibc.overrideDerivation (old: {
postInstall = old.postInstall + ''
touch $out/MODIFIED_GLIBC
'';
});
binutils = pkgs.binutils.override {
libc = glibc;
};
gcc = pkgs.gcc.override {
bintools = binutils;
libc = glibc;
};
in
builtins.trace "Enabling Custom Stdenv" pkgs.stdenv.override {
cc = gcc;
overrides = self: super: {
inherit glibc binutils gcc;
};
allowedRequisites = pkgs.stdenv.allowedRequisites ++
[ glibc.out glibc.dev glibc.bin binutils ];
};
};
} Trying to build zlib on staging branch with the new stdenv including a modified glibc: $ nix-build ./replaceStdenv.nix -A zlib
trace: Enabling Custom Stdenv
error: infinite recursion encountered
at //builtin/derivation.nix:19:19:
(use '--show-trace' to show detailed location information) and with this PR: $ nix-build ./replaceStdenv.nix -A zlib --arg useFix true
trace: Enabling Custom Stdenv
these 5 derivations will be built:
/nix/store/fkdsf4v540z6x2yih9s3m0hdj3z9q7w6-glibc-2.34-115.drv
/nix/store/66lf3rh9yfa749ly8d3r6y13cmxs1722-binutils-wrapper-2.38.drv
/nix/store/ys3nch468bsmqc2k7hx17ji27ix9bxc1-gcc-wrapper-11.2.0.drv
/nix/store/a0wlkrmzzckajx7zjm6wi215x0i64p9b-stdenv-linux.drv
/nix/store/9lc9dy9lni7fgh0l58yazxkxyadcnp7f-zlib-1.2.12.drv
building '/nix/store/fkdsf4v540z6x2yih9s3m0hdj3z9q7w6-glibc-2.34-115.drv'...
unpacking sources
unpacking source archive /nix/store/wjbv1k6yigmb280wrvc1gkv8cnrsacij-glibc-2.34.tar.xz
^Cerror: interrupted by the user |
This avoids infinite recursion when using config.replaceStdenv
Any dependency update on autoconf, automake, libtool or gettext breaks the bootstrapping of fetchurl with replaceStdenv. This patchs removes autoconfHook and avoid automake when building coreutils.
6a09a0d
to
e2adbbf
Compare
This has been updated for new staging changes |
Hi, as a small testing overview you could read to #144747 (comment) |
I also use this patch to build shared library for ubuntu with older glibc, and can confirm it works. If nixpkgs is switched to original one here: https://github.com/CertainLach/VivePro2-Linux-Driver/blob/master/flake.nix#L4 |
Tl;DR: I think to get away without patching --- replaceStdenv__.nix 2023-01-07 15:58:52.797881651 +0000
+++ replaceStdenv_.nix 2023-01-07 15:58:50.613852468 +0000
@@ -1,90 +1,91 @@
import ./. {
config = {
replaceStdenv = { pkgs }: let
# Bootstrap a new stdenv that includes our nss_sss in glibc
glibc = pkgs.glibc.overrideDerivation (old: {
postInstall = old.postInstall + ''
ln -s ${pkgs.nss_sss}/lib/*.so.* $out/lib
'';
});
binutils = pkgs.binutils.override {
libc = glibc;
};
gcc = pkgs.gcc.override {
bintools = binutils;
libc = glibc;
};
in
builtins.trace "Enabling Custom Stdenv" pkgs.stdenv.override {
cc = gcc;
overrides = self: super: {
inherit glibc binutils gcc;
+ inherit (pkgs) fetchurl;
};
allowedRequisites = pkgs.stdenv.allowedRequisites ++
[ glibc.out glibc.dev glibc.bin binutils pkgs.nss_sss ];
};
}; That allows me to build More words on why overriding bootstrap packages is hard, especially In bootstrap it takes us a few
Changing Looking at your change in:
This one is especially worrying: You also have AFAIU currently Hope that helps a bit. |
autoreconfHook = null; | ||
texinfo = null; | ||
}).overrideAttrs (_: { | ||
preBuild = "touch Makefile.in"; # avoid automake | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this change should not be needed if your overrides don't trigger a rebuild of fetchurl
. If you do need to rebuild fetchurl
I would suggest handling in the rest of overrides (added a separate longer comment as an alternative not to rebuild fetchpatch
). WDYT?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As someone who just used this patch: I'd defer to the simpler user-facing API (i.e. not asking the user to predicate behavior on whether or not fetchurl
needed to be rebuilt). If I understand correctly, you're (@trofi) recommending some support to prevent users from needing to rebuild some things in some particular cases. However, in the case that you're doing so much work that you're rebuilding fetchurl
you're probably okay paying the price to rebuild fetchpatch
et al.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't worry about the rebuilds. The problem happened here because the overlay introduced a dependency cycle which was not there initially. The change is a workaround for a specific case of newly introduced loop.
It's a workaround I don't feel good about: conditionally disabling autoreconf
on coreutils
is not great. It would be easier to accept the change if it was a change that strips (or adds) some dependencies unconditionally.
If others think this change is reasonable to break this particular loop type then so be it. I still think it's the overlay user's responsibility to untangle new dependency cycles they introduce.
And to state the obvious: i'm not an authority on stdenv
(or anything in nixpkgs
).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, I misunderstood. It seems like you're saying that this change to fetchurl
is necessary because of the "solution". It's not that an unchanged fetchurl
was the source of the original infinite recursion. Is that right? If so, then I agree that this doesn't seem like the best way to go.
Also, while I claimed that this "fixed my issue", I guess I can only say that it resolved the infinite recursion for me. After building a lot of stuff I actually still saw failure to build cpio
(even though it solved the infinite recursion failure) - nix log
is attached below. I'm hoping/thinking this was related to a libcxx
version (I'm using libcxxStdenv
) and am retrying on 24.11 (more on that, below).
6akz7axh5y7393qm0a8w4n5nwkb0wjvp-cpio-2.13.drv.log
I have a few follow-up questions, since you seem to have a pretty deep working understanding of bootstrap
and how stdenv
's are defined.
- I initially tried to use this work as-is (point
nixpkgs
to this fork) but ran into an issue buildingcpio
(see above). So, then I tried to use this patch on24.11
and ran into an infinite recursion. How did @dguibert track down those packages which were related to infinite recursions? Or, how would someone, generally?
$ nix build .\#defaultLibcxxStdenv --show-trace --override-input nixpkgs $HOME/code/repos/others/nixos/nixpkgs
warning: Git tree '/home/john/code/repos/mine/f-u' is dirty
warning: Git tree '/home/john/code/repos/others/nixos/nixpkgs' is dirty
warning: not writing modified lock file of flake 'git+file:///home/john/code/repos/mine/f-u':
• Updated input 'nixpkgs':
'github:dguibert/nixpkgs/e2adbbf71a6d6e49ecf2f66e48acdbab2dccdaa3' (2022-11-18)
→ 'git+file:///home/john/code/repos/others/nixos/nixpkgs' (2024-11-28)
trace: Enabling Custom Stdenv
error:
… while calling the 'derivationStrict' builtin
at /builtin/derivation.nix:9:12: (source not available)
… while evaluating derivation 'f-u++'
whose name attribute is located at /nix/store/93ixbis1xdzcq6jjbnkc2kv72qsgg5h8-source/pkgs/stdenv/generic/make-derivation.nix:336:7
… while evaluating attribute 'buildInputs' of derivation 'f-u++'
at /nix/store/93ixbis1xdzcq6jjbnkc2kv72qsgg5h8-source/pkgs/stdenv/generic/make-derivation.nix:383:7:
382| depsHostHost = elemAt (elemAt dependencies 1) 0;
383| buildInputs = elemAt (elemAt dependencies 1) 1;
| ^
384| depsTargetTarget = elemAt (elemAt dependencies 2) 0;
… while evaluating derivation 'nix-2.24.10'
whose name attribute is located at /nix/store/93ixbis1xdzcq6jjbnkc2kv72qsgg5h8-source/pkgs/stdenv/generic/make-derivation.nix:336:7
… while evaluating attribute 'buildInputs' of derivation 'nix-2.24.10'
at /nix/store/93ixbis1xdzcq6jjbnkc2kv72qsgg5h8-source/pkgs/stdenv/generic/make-derivation.nix:383:7:
382| depsHostHost = elemAt (elemAt dependencies 1) 0;
383| buildInputs = elemAt (elemAt dependencies 1) 1;
| ^
384| depsTargetTarget = elemAt (elemAt dependencies 2) 0;
… while evaluating derivation 'brotli-1.1.0'
whose name attribute is located at /nix/store/93ixbis1xdzcq6jjbnkc2kv72qsgg5h8-source/pkgs/stdenv/generic/make-derivation.nix:336:7
… while evaluating attribute 'nativeBuildInputs' of derivation 'brotli-1.1.0'
at /nix/store/93ixbis1xdzcq6jjbnkc2kv72qsgg5h8-source/pkgs/stdenv/generic/make-derivation.nix:380:7:
379| depsBuildBuild = elemAt (elemAt dependencies 0) 0;
380| nativeBuildInputs = elemAt (elemAt dependencies 0) 1;
| ^
381| depsBuildTarget = elemAt (elemAt dependencies 0) 2;
… while evaluating derivation 'cmake-3.30.5'
whose name attribute is located at /nix/store/93ixbis1xdzcq6jjbnkc2kv72qsgg5h8-source/pkgs/stdenv/generic/make-derivation.nix:336:7
… while evaluating attribute 'buildInputs' of derivation 'cmake-3.30.5'
at /nix/store/93ixbis1xdzcq6jjbnkc2kv72qsgg5h8-source/pkgs/stdenv/generic/make-derivation.nix:383:7:
382| depsHostHost = elemAt (elemAt dependencies 1) 0;
383| buildInputs = elemAt (elemAt dependencies 1) 1;
| ^
384| depsTargetTarget = elemAt (elemAt dependencies 2) 0;
… while evaluating derivation 'libarchive-3.7.7'
whose name attribute is located at /nix/store/93ixbis1xdzcq6jjbnkc2kv72qsgg5h8-source/pkgs/stdenv/generic/make-derivation.nix:336:7
… while evaluating attribute 'buildInputs' of derivation 'libarchive-3.7.7'
at /nix/store/93ixbis1xdzcq6jjbnkc2kv72qsgg5h8-source/pkgs/stdenv/generic/make-derivation.nix:383:7:
382| depsHostHost = elemAt (elemAt dependencies 1) 0;
383| buildInputs = elemAt (elemAt dependencies 1) 1;
| ^
384| depsTargetTarget = elemAt (elemAt dependencies 2) 0;
… while evaluating derivation 'e2fsprogs-1.47.1'
whose name attribute is located at /nix/store/93ixbis1xdzcq6jjbnkc2kv72qsgg5h8-source/pkgs/stdenv/generic/make-derivation.nix:336:7
… while evaluating attribute 'buildInputs' of derivation 'e2fsprogs-1.47.1'
at /nix/store/93ixbis1xdzcq6jjbnkc2kv72qsgg5h8-source/pkgs/stdenv/generic/make-derivation.nix:383:7:
382| depsHostHost = elemAt (elemAt dependencies 1) 0;
383| buildInputs = elemAt (elemAt dependencies 1) 1;
| ^
384| depsTargetTarget = elemAt (elemAt dependencies 2) 0;
… while evaluating derivation 'fuse-3.16.2'
whose name attribute is located at /nix/store/93ixbis1xdzcq6jjbnkc2kv72qsgg5h8-source/pkgs/stdenv/generic/make-derivation.nix:336:7
… while evaluating attribute 'nativeBuildInputs' of derivation 'fuse-3.16.2'
at /nix/store/93ixbis1xdzcq6jjbnkc2kv72qsgg5h8-source/pkgs/stdenv/generic/make-derivation.nix:380:7:
379| depsBuildBuild = elemAt (elemAt dependencies 0) 0;
380| nativeBuildInputs = elemAt (elemAt dependencies 0) 1;
| ^
381| depsBuildTarget = elemAt (elemAt dependencies 0) 2;
… while evaluating derivation 'meson-1.6.0'
whose name attribute is located at /nix/store/93ixbis1xdzcq6jjbnkc2kv72qsgg5h8-source/pkgs/stdenv/generic/make-derivation.nix:336:7
… while evaluating attribute 'buildInputs' of derivation 'meson-1.6.0'
at /nix/store/93ixbis1xdzcq6jjbnkc2kv72qsgg5h8-source/pkgs/stdenv/generic/make-derivation.nix:383:7:
382| depsHostHost = elemAt (elemAt dependencies 1) 0;
383| buildInputs = elemAt (elemAt dependencies 1) 1;
| ^
384| depsTargetTarget = elemAt (elemAt dependencies 2) 0;
… while evaluating derivation 'openmp-18.1.8'
whose name attribute is located at /nix/store/93ixbis1xdzcq6jjbnkc2kv72qsgg5h8-source/pkgs/stdenv/generic/make-derivation.nix:336:7
… while evaluating attribute 'buildInputs' of derivation 'openmp-18.1.8'
at /nix/store/93ixbis1xdzcq6jjbnkc2kv72qsgg5h8-source/pkgs/stdenv/generic/make-derivation.nix:383:7:
382| depsHostHost = elemAt (elemAt dependencies 1) 0;
383| buildInputs = elemAt (elemAt dependencies 1) 1;
| ^
384| depsTargetTarget = elemAt (elemAt dependencies 2) 0;
… while evaluating derivation 'llvm-18.1.8'
whose name attribute is located at /nix/store/93ixbis1xdzcq6jjbnkc2kv72qsgg5h8-source/pkgs/stdenv/generic/make-derivation.nix:336:7
… while evaluating attribute 'nativeBuildInputs' of derivation 'llvm-18.1.8'
at /nix/store/93ixbis1xdzcq6jjbnkc2kv72qsgg5h8-source/pkgs/stdenv/generic/make-derivation.nix:380:7:
379| depsBuildBuild = elemAt (elemAt dependencies 0) 0;
380| nativeBuildInputs = elemAt (elemAt dependencies 0) 1;
| ^
381| depsBuildTarget = elemAt (elemAt dependencies 0) 2;
error: infinite recursion encountered
at «none»:0: (source not available)
- In @dguibert's minimal reproduction he did more than just pull in this patch, he also redefines
glibc
,binutils
, andgcc
and then does some magic with them:
replaceStdenv = { pkgs }: let
# Bootstrap a new stdenv that includes a modified glibc
glibc = pkgs.glibc.overrideDerivation (old: {
postInstall = old.postInstall + ''
touch $out/MODIFIED_GLIBC
'';
});
binutils = pkgs.binutils.override {
libc = glibc;
};
gcc = pkgs.gcc.override {
bintools = binutils;
libc = glibc;
};
in
builtins.trace "Enabling Custom Stdenv" pkgs.stdenv.override {
cc = gcc;
overrides = self: super: {
inherit glibc binutils gcc;
};
allowedRequisites = pkgs.stdenv.allowedRequisites ++
[ glibc.out glibc.dev glibc.bin binutils ];
};
I found this was necessary on top of 24.11
(at least, it alleviated the infinite recursion at eval-time - it remains to be seen if cpio
is in any better state). Do you think something like this is generally necessary, or did I just "luck out" in that it fixed my eval issue?
- How would you recommend solving this problem, instead?
Of course, but this used to work. Adding autoreconfHook to openssl and adding zlib to perl break the config.replaceStdenv feature, see Commit 3a78980 where autoreconfHook is fixed. I've just wanted to restore this feature I used since many years. Then we could discuss how to enhance the overriding of glibc from early stages (see #50329 and #129595)
Good point, thanks. |
Just to clarify: what exactly you expect to work? I try to understand if it's one of:
My worry is that change things like that about
Oh, that's quite an invasive change into I would say that change should be reverted to simplify To draw an analogy you hard to rewrap Or you could add an arbitrarily heavy package to
I'm not an expert but scarce documentation and implemntation of
Can you help me understand why What are your thoughts? Should we still pursue complicating |
@dguibert where do we stand progress-wise? Any interest or bandwidth to continue pursuing this? |
My main concern was that it used to work (for quite some years) and a patch broke that. I also understand that my override might not have use the right fetchurl. |
I'm able to reproduce the issue this PR aims to solve: pkgs = import nixpkgs {
config.replaceStdenv = { pkgs }: pkgs.clangStdenv;
}; This PR seems dead though :( |
I think adding |
Hi,
I'm not able to reproduce with a file { useFix ? false }:
let
nixpkgs = if useFix then
(builtins.fetchGit {
url = "https://github.com/dguibert/nixpkgs";
ref = "refs/heads/dg/fix-replacestdenv-coreutils";
})
else
(builtins.fetchGit {
url = "https://github.com/NixOS/nixpkgs";
ref = "refs/heads/staging";
});
pkgs = import nixpkgs {
config.replaceStdenv = { pkgs }: pkgs.clangStdenv;
};
in pkgs // {
zlib_ = pkgs.zlib.override { stdenv = pkgs.clangStdenv; };
} nix build -L -f nixpkgs-144747-bis.nix zlib
[...]
build flags: -j2 SHELL=/nix/store/razasrvdg7ckplfmvdxv4ia3wbayr94s-bootstrap-tools/bin/bash PREFIX= SHARED_MODE=1
gcc -O3 -D_LARGEFILE64_SOURCE=1 -DHAVE_HIDDEN -I. -c -o example.o test/example.c
gcc -O3 -D_LARGEFILE64_SOURCE=1 -DHAVE_HIDDEN -c -o adler32.o adler32.c
[...] It builds with gcc where it should use |
@dguibert I just used this PR branch to unblock me on a project. Big thanks for drafting this work! It'd be awesome to come to some consensus, here, in order to merge. |
This avoids infinite recursion when using config.replaceStdenv
Motivation for this change
Things done
sandbox = true
set innix.conf
? (See Nix manual)nix-shell -p nixpkgs-review --run "nixpkgs-review wip"
./result/bin/
)