treewide: Leverage new top-level libc in bootstrap, and simplify

Picking up where #414321 left off, we can now simplify some things by
using `pkgs.libc` or `targetPackages.libc` consistently.

Individual packages should probably continue using `stdenv.cc.libc`, for
now at least, since it is possible they are given a `stdenv.cc` with an
alternative libc, but for the treewide code, the top-level `libc`
package is preferable and easier to work with.

Co-authored-by: Tristan Ross <rosscomputerguy@protonmail.com>
This commit is contained in:
John Ericson 2025-06-06 14:35:15 -04:00
parent bfc3acf8f3
commit 1c6586455c
7 changed files with 93 additions and 80 deletions

View file

@ -242,7 +242,7 @@ self: super:
buildPackages.stdenv.cc buildPackages.stdenv.cc
] ]
++ lib.optionals stdenv.hostPlatform.isStatic [ ++ lib.optionals stdenv.hostPlatform.isStatic [
(xorg.buildPackages.stdenv.cc.libc.static or null) (xorg.buildPackages.libc.static or null)
]; ];
preConfigure = '' preConfigure = ''
sed 's,^as_dummy.*,as_dummy="\$PATH",' -i configure sed 's,^as_dummy.*,as_dummy="\$PATH",' -i configure

View file

@ -132,7 +132,7 @@ let
bintools = prevStage.darwin.binutils; bintools = prevStage.darwin.binutils;
isClang = true; isClang = true;
libc = prevStage.darwin.libSystem; inherit (prevStage) libc;
inherit (prevStage.llvmPackages) libcxx; inherit (prevStage.llvmPackages) libcxx;
inherit lib; inherit lib;
@ -582,7 +582,10 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check
assert allDeps isFromNixpkgs [ assert allDeps isFromNixpkgs [
(sdkPackagesNoCC prevStage) (sdkPackagesNoCC prevStage)
{ inherit (prevStage.darwin) binutils libSystem; } {
inherit (prevStage.darwin) binutils libSystem;
inherit (prevStage) libc;
}
]; ];
stageFun prevStage { stageFun prevStage {
@ -1260,6 +1263,7 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check
assert isBuiltByNixpkgsCompiler prevStage.darwin.sigtool; assert isBuiltByNixpkgsCompiler prevStage.darwin.sigtool;
assert isFromNixpkgs prevStage.darwin.libSystem; assert isFromNixpkgs prevStage.darwin.libSystem;
assert isFromNixpkgs prevStage.libc;
assert isFromNixpkgs prevStage.darwin.binutils-unwrapped; assert isFromNixpkgs prevStage.darwin.binutils-unwrapped;
assert isBuiltByNixpkgsCompiler prevStage.llvmPackages.clang-unwrapped; assert isBuiltByNixpkgsCompiler prevStage.llvmPackages.clang-unwrapped;

View file

@ -158,8 +158,6 @@ let
isFromBootstrapFiles = true; isFromBootstrapFiles = true;
}; };
getLibc = stage: stage.${localSystem.libc};
# This function builds the various standard environments used during # This function builds the various standard environments used during
# the bootstrap. In all stages, we build an stdenv and the package # the bootstrap. In all stages, we build an stdenv and the package
# set that can be built with that stdenv. # set that can be built with that stdenv.
@ -207,7 +205,7 @@ let
cc = prevStage.gcc-unwrapped; cc = prevStage.gcc-unwrapped;
bintools = prevStage.binutils; bintools = prevStage.binutils;
isGNU = true; isGNU = true;
libc = getLibc prevStage; inherit (prevStage) libc;
inherit lib; inherit lib;
inherit (prevStage) coreutils gnugrep; inherit (prevStage) coreutils gnugrep;
stdenvNoCC = prevStage.ccWrapperStdenv; stdenvNoCC = prevStage.ccWrapperStdenv;
@ -221,7 +219,7 @@ let
postFixup = postFixup =
(a.postFixup or "") (a.postFixup or "")
+ '' + ''
echo "--sysroot=${lib.getDev (getLibc prevStage)}" >> $out/nix-support/cc-cflags echo "--sysroot=${lib.getDev prevStage.libc}" >> $out/nix-support/cc-cflags
''; '';
} }
); );
@ -293,9 +291,13 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check
nativeTools = false; nativeTools = false;
nativeLibc = false; nativeLibc = false;
expand-response-params = ""; expand-response-params = "";
libc = getLibc self;
inherit lib; inherit lib;
inherit (self) stdenvNoCC coreutils gnugrep; inherit (self)
stdenvNoCC
coreutils
gnugrep
libc
;
bintools = bootstrapTools; bintools = bootstrapTools;
runtimeShell = "${bootstrapTools}/bin/bash"; runtimeShell = "${bootstrapTools}/bin/bash";
}; };
@ -320,6 +322,7 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check
# previous stage0 stdenv: # previous stage0 stdenv:
assert isFromBootstrapFiles prevStage.binutils.bintools; assert isFromBootstrapFiles prevStage.binutils.bintools;
assert isFromBootstrapFiles prevStage."${localSystem.libc}"; assert isFromBootstrapFiles prevStage."${localSystem.libc}";
assert isFromBootstrapFiles prevStage.libc;
assert isFromBootstrapFiles prevStage.gcc-unwrapped; assert isFromBootstrapFiles prevStage.gcc-unwrapped;
assert isFromBootstrapFiles prevStage.coreutils; assert isFromBootstrapFiles prevStage.coreutils;
assert isFromBootstrapFiles prevStage.gnugrep; assert isFromBootstrapFiles prevStage.gnugrep;
@ -339,7 +342,7 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check
binutils binutils
; ;
${localSystem.libc} = getLibc prevStage; ${localSystem.libc} = prevStage.${localSystem.libc};
# A threaded perl build needs glibc/libpthread_nonshared.a, # A threaded perl build needs glibc/libpthread_nonshared.a,
# which is not included in bootstrapTools, so disable threading. # which is not included in bootstrapTools, so disable threading.
@ -374,6 +377,7 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check
prevStage: prevStage:
assert isBuiltByBootstrapFilesCompiler prevStage.binutils-unwrapped; assert isBuiltByBootstrapFilesCompiler prevStage.binutils-unwrapped;
assert isFromBootstrapFiles prevStage."${localSystem.libc}"; assert isFromBootstrapFiles prevStage."${localSystem.libc}";
assert isFromBootstrapFiles prevStage.libc;
assert isFromBootstrapFiles prevStage.gcc-unwrapped; assert isFromBootstrapFiles prevStage.gcc-unwrapped;
assert isFromBootstrapFiles prevStage.coreutils; assert isFromBootstrapFiles prevStage.coreutils;
assert isFromBootstrapFiles prevStage.gnugrep; assert isFromBootstrapFiles prevStage.gnugrep;
@ -393,7 +397,7 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check
perl perl
patchelf patchelf
; ;
${localSystem.libc} = getLibc prevStage; ${localSystem.libc} = prevStage.${localSystem.libc};
gmp = super.gmp.override { cxx = false; }; gmp = super.gmp.override { cxx = false; };
# This stage also rebuilds binutils which will of course be used only in the next stage. # This stage also rebuilds binutils which will of course be used only in the next stage.
# We inherit this until stage3, in stage4 it will be rebuilt using the adjacent bash/runtimeShell pkg. # We inherit this until stage3, in stage4 it will be rebuilt using the adjacent bash/runtimeShell pkg.
@ -484,6 +488,7 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check
# previous stage1 stdenv: # previous stage1 stdenv:
assert isBuiltByBootstrapFilesCompiler prevStage.binutils-unwrapped; assert isBuiltByBootstrapFilesCompiler prevStage.binutils-unwrapped;
assert isFromBootstrapFiles prevStage."${localSystem.libc}"; assert isFromBootstrapFiles prevStage."${localSystem.libc}";
assert isFromBootstrapFiles prevStage.libc;
assert isBuiltByBootstrapFilesCompiler prevStage.gcc-unwrapped; assert isBuiltByBootstrapFilesCompiler prevStage.gcc-unwrapped;
assert isFromBootstrapFiles prevStage.coreutils; assert isFromBootstrapFiles prevStage.coreutils;
assert isFromBootstrapFiles prevStage.gnugrep; assert isFromBootstrapFiles prevStage.gnugrep;
@ -508,6 +513,9 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check
doCheck = false; doCheck = false;
}); });
# Avoids infinite recursion, as this is in the build-time dependencies of libc.
libiconv = self.libcIconv prevStage.libc;
# We need libidn2 and its dependency libunistring as glibc dependency. # We need libidn2 and its dependency libunistring as glibc dependency.
# To avoid the cycle, we build against bootstrap libc, nuke references, # To avoid the cycle, we build against bootstrap libc, nuke references,
# and use the result as input for our final glibc. We also pass this pair # and use the result as input for our final glibc. We also pass this pair
@ -538,7 +546,7 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check
binutils = prevStage.binutils.override { binutils = prevStage.binutils.override {
# Rewrap the binutils with the new glibc, so both the next # Rewrap the binutils with the new glibc, so both the next
# stage's wrappers use it. # stage's wrappers use it.
libc = getLibc self; inherit (self) libc;
# Unfortunately, when building gcc in the next stage, its LTO plugin # Unfortunately, when building gcc in the next stage, its LTO plugin
# would use the final libc but `ld` would use the bootstrap one, # would use the final libc but `ld` would use the bootstrap one,
@ -557,8 +565,8 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check
mkdir -p "$out"/bin mkdir -p "$out"/bin
cp -a '${prevStage.bintools.bintools}'/bin/* "$out"/bin/ cp -a '${prevStage.bintools.bintools}'/bin/* "$out"/bin/
chmod +w "$out"/bin/ld.bfd chmod +w "$out"/bin/ld.bfd
patchelf --set-interpreter '${getLibc self}'/lib/ld*.so.? \ patchelf --set-interpreter '${self.libc}'/lib/ld*.so.? \
--set-rpath "${getLibc self}/lib:$(patchelf --print-rpath "$out"/bin/ld.bfd)" \ --set-rpath "${self.libc}/lib:$(patchelf --print-rpath "$out"/bin/ld.bfd)" \
"$out"/bin/ld.bfd "$out"/bin/ld.bfd
''; '';
}; };
@ -589,6 +597,7 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check
# previous stage2 stdenv: # previous stage2 stdenv:
assert isBuiltByNixpkgsCompiler prevStage.binutils-unwrapped; assert isBuiltByNixpkgsCompiler prevStage.binutils-unwrapped;
assert isBuiltByNixpkgsCompiler prevStage.${localSystem.libc}; assert isBuiltByNixpkgsCompiler prevStage.${localSystem.libc};
assert isBuiltByNixpkgsCompiler prevStage.libc;
assert isBuiltByBootstrapFilesCompiler prevStage.gcc-unwrapped; assert isBuiltByBootstrapFilesCompiler prevStage.gcc-unwrapped;
assert isFromBootstrapFiles prevStage.coreutils; assert isFromBootstrapFiles prevStage.coreutils;
assert isFromBootstrapFiles prevStage.gnugrep; assert isFromBootstrapFiles prevStage.gnugrep;
@ -625,7 +634,7 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check
gmp = super.gmp.override { cxx = false; }; gmp = super.gmp.override { cxx = false; };
} }
// { // {
${localSystem.libc} = getLibc prevStage; ${localSystem.libc} = prevStage.${localSystem.libc};
gcc-unwrapped = gcc-unwrapped =
(super.gcc-unwrapped.override ( (super.gcc-unwrapped.override (
commonGccOverrides commonGccOverrides
@ -661,6 +670,7 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check
# previous stage3 stdenv: # previous stage3 stdenv:
assert isBuiltByNixpkgsCompiler prevStage.binutils-unwrapped; assert isBuiltByNixpkgsCompiler prevStage.binutils-unwrapped;
assert isBuiltByNixpkgsCompiler prevStage.${localSystem.libc}; assert isBuiltByNixpkgsCompiler prevStage.${localSystem.libc};
assert isBuiltByNixpkgsCompiler prevStage.libc;
assert isBuiltByNixpkgsCompiler prevStage.gcc-unwrapped; assert isBuiltByNixpkgsCompiler prevStage.gcc-unwrapped;
assert isFromBootstrapFiles prevStage.coreutils; assert isFromBootstrapFiles prevStage.coreutils;
assert isFromBootstrapFiles prevStage.gnugrep; assert isFromBootstrapFiles prevStage.gnugrep;
@ -684,7 +694,7 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check
libidn2 libidn2
libunistring libunistring
; ;
${localSystem.libc} = getLibc prevStage; ${localSystem.libc} = prevStage.${localSystem.libc};
# Since this is the first fresh build of binutils since stage2, our own runtimeShell will be used. # Since this is the first fresh build of binutils since stage2, our own runtimeShell will be used.
binutils = super.binutils.override { binutils = super.binutils.override {
# Build expand-response-params with last stage like below # Build expand-response-params with last stage like below
@ -702,13 +712,13 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check
inherit (prevStage) expand-response-params; inherit (prevStage) expand-response-params;
cc = prevStage.gcc-unwrapped; cc = prevStage.gcc-unwrapped;
bintools = self.binutils; bintools = self.binutils;
libc = getLibc self;
inherit lib; inherit lib;
inherit (self) inherit (self)
stdenvNoCC stdenvNoCC
coreutils coreutils
gnugrep gnugrep
runtimeShell runtimeShell
libc
; ;
fortify-headers = self.fortify-headers; fortify-headers = self.fortify-headers;
}; };
@ -736,6 +746,7 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check
# which applies here as well. # which applies here as well.
assert isBuiltByNixpkgsCompiler prevStage.binutils-unwrapped; assert isBuiltByNixpkgsCompiler prevStage.binutils-unwrapped;
assert isBuiltByNixpkgsCompiler prevStage.${localSystem.libc}; assert isBuiltByNixpkgsCompiler prevStage.${localSystem.libc};
assert isBuiltByNixpkgsCompiler prevStage.libc;
assert isBuiltByNixpkgsCompiler prevStage.gcc-unwrapped; assert isBuiltByNixpkgsCompiler prevStage.gcc-unwrapped;
assert isBuiltByNixpkgsCompiler prevStage.coreutils; assert isBuiltByNixpkgsCompiler prevStage.coreutils;
assert isBuiltByNixpkgsCompiler prevStage.gnugrep; assert isBuiltByNixpkgsCompiler prevStage.gnugrep;
@ -843,7 +854,7 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check
libunistring libunistring
] ]
# More complicated cases # More complicated cases
++ (map (x: lib.getOutput x (getLibc prevStage)) [ ++ (map (x: lib.getOutput x (prevStage.libc)) [
"out" "out"
"dev" "dev"
"bin" "bin"
@ -893,7 +904,7 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check
libunistring libunistring
; ;
inherit (prevStage.gnugrep) pcre2; inherit (prevStage.gnugrep) pcre2;
${localSystem.libc} = getLibc prevStage; ${localSystem.libc} = prevStage.${localSystem.libc};
# Hack: avoid libidn2.{bin,dev} referencing bootstrap tools. There's a logical cycle. # Hack: avoid libidn2.{bin,dev} referencing bootstrap tools. There's a logical cycle.
libidn2 = import ../../development/libraries/libidn2/no-bootstrap-reference.nix { libidn2 = import ../../development/libraries/libidn2/no-bootstrap-reference.nix {
@ -925,6 +936,7 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check
# which applies here as well. # which applies here as well.
assert isBuiltByNixpkgsCompiler prevStage.binutils-unwrapped; assert isBuiltByNixpkgsCompiler prevStage.binutils-unwrapped;
assert isBuiltByNixpkgsCompiler prevStage.${localSystem.libc}; assert isBuiltByNixpkgsCompiler prevStage.${localSystem.libc};
assert isBuiltByNixpkgsCompiler prevStage.libc;
assert isBuiltByNixpkgsCompiler prevStage.gcc-unwrapped; assert isBuiltByNixpkgsCompiler prevStage.gcc-unwrapped;
assert isBuiltByNixpkgsCompiler prevStage.coreutils; assert isBuiltByNixpkgsCompiler prevStage.coreutils;
assert isBuiltByNixpkgsCompiler prevStage.gnugrep; assert isBuiltByNixpkgsCompiler prevStage.gnugrep;

View file

@ -3,9 +3,12 @@
}: }:
let let
inherit (pkgs) lib stdenv config; inherit (pkgs)
lib
libc = pkgs.stdenv.cc.libc; stdenv
config
libc
;
patchelf = pkgs.patchelf.overrideAttrs (previousAttrs: { patchelf = pkgs.patchelf.overrideAttrs (previousAttrs: {
NIX_CFLAGS_COMPILE = (previousAttrs.NIX_CFLAGS_COMPILE or [ ]) ++ [ NIX_CFLAGS_COMPILE = (previousAttrs.NIX_CFLAGS_COMPILE or [ ]) ++ [

View file

@ -6181,7 +6181,7 @@ with pkgs;
wrapBintoolsWith = wrapBintoolsWith =
{ {
bintools, bintools,
libc ? if stdenv.targetPlatform != stdenv.hostPlatform then targetPackages.libc else stdenv.cc.libc, libc ? targetPackages.libc or pkgs.libc,
... ...
}@extraArgs: }@extraArgs:
callPackage ../build-support/bintools-wrapper ( callPackage ../build-support/bintools-wrapper (
@ -8198,57 +8198,53 @@ with pkgs;
# We can choose: # We can choose:
libc = libc =
if stdenv.hostPlatform == stdenv.buildPlatform then let
# TODO get rid of this branch after the native boostrap is reworked inherit (stdenv.hostPlatform) libc;
stdenv.cc.libc # libc is hackily often used from the previous stage. This `or`
# hack fixes the hack, *sigh*.
in
if libc == null then
null
else if libc == "glibc" then
glibc
else if libc == "bionic" then
bionic
else if libc == "uclibc" then
uclibc
else if libc == "avrlibc" then
avrlibc
else if libc == "newlib" && stdenv.hostPlatform.isMsp430 then
msp430Newlib
else if libc == "newlib" && stdenv.hostPlatform.isVc4 then
vc4-newlib
else if libc == "newlib" && stdenv.hostPlatform.isOr1k then
or1k-newlib
else if libc == "newlib" then
newlib
else if libc == "newlib-nano" then
newlib-nano
else if libc == "musl" then
musl
else if libc == "msvcrt" then
windows.mingw_w64
else if libc == "ucrt" then
windows.mingw_w64
else if libc == "libSystem" then
if stdenv.hostPlatform.useiOSPrebuilt then darwin.iosSdkPkgs.libraries else darwin.libSystem
else if libc == "fblibc" then
freebsd.libc
else if libc == "oblibc" then
openbsd.libc
else if libc == "nblibc" then
netbsd.libc
else if libc == "wasilibc" then
wasilibc
else if libc == "relibc" then
relibc
else if name == "llvm" then
llvmPackages_20.libc
else else
let throw "Unknown libc ${libc}";
inherit (stdenv.hostPlatform) libc;
# libc is hackily often used from the previous stage. This `or`
# hack fixes the hack, *sigh*.
in
if libc == null then
null
else if libc == "glibc" then
glibc
else if libc == "bionic" then
bionic
else if libc == "uclibc" then
uclibc
else if libc == "avrlibc" then
avrlibc
else if libc == "newlib" && stdenv.hostPlatform.isMsp430 then
msp430Newlib
else if libc == "newlib" && stdenv.hostPlatform.isVc4 then
vc4-newlib
else if libc == "newlib" && stdenv.hostPlatform.isOr1k then
or1k-newlib
else if libc == "newlib" then
newlib
else if libc == "newlib-nano" then
newlib-nano
else if libc == "musl" then
musl
else if libc == "msvcrt" then
windows.mingw_w64
else if libc == "ucrt" then
windows.mingw_w64
else if libc == "libSystem" then
if stdenv.hostPlatform.useiOSPrebuilt then darwin.iosSdkPkgs.libraries else darwin.libSystem
else if libc == "fblibc" then
freebsd.libc
else if libc == "oblibc" then
openbsd.libc
else if libc == "nblibc" then
netbsd.libc
else if libc == "wasilibc" then
wasilibc
else if libc == "relibc" then
relibc
else if name == "llvm" then
llvmPackages_20.libc
else
throw "Unknown libc ${libc}";
threads = threads =
lib.optionalAttrs (stdenv.hostPlatform.isMinGW && !(stdenv.hostPlatform.useLLVM or false)) lib.optionalAttrs (stdenv.hostPlatform.isMinGW && !(stdenv.hostPlatform.useLLVM or false))
@ -8772,7 +8768,7 @@ with pkgs;
"fblibc" "fblibc"
] ]
then then
libcIconv (if stdenv.hostPlatform != stdenv.buildPlatform then libc else stdenv.cc.libc) libcIconv pkgs.libc
else if stdenv.hostPlatform.isDarwin then else if stdenv.hostPlatform.isDarwin then
darwin.libiconv darwin.libiconv
else else
@ -8798,7 +8794,7 @@ with pkgs;
"musl" "musl"
] ]
then then
lib.getBin stdenv.cc.libc lib.getBin libc
else if stdenv.hostPlatform.isDarwin then else if stdenv.hostPlatform.isDarwin then
lib.getBin libiconv lib.getBin libiconv
else if stdenv.hostPlatform.isFreeBSD then else if stdenv.hostPlatform.isFreeBSD then

View file

@ -56,8 +56,7 @@ makeScopeWithSplicing' {
}; };
binutils = pkgs.wrapBintoolsWith { binutils = pkgs.wrapBintoolsWith {
libc = inherit (targetPackages) libc;
if stdenv.targetPlatform != stdenv.hostPlatform then targetPackages.libc else pkgs.stdenv.cc.libc;
bintools = self.binutils-unwrapped; bintools = self.binutils-unwrapped;
}; };

View file

@ -95,7 +95,7 @@ let
linux = pkgs.util-linux; linux = pkgs.util-linux;
}; };
getconf = { getconf = {
linux = if stdenv.hostPlatform.libc == "glibc" then pkgs.stdenv.cc.libc else pkgs.netbsd.getconf; linux = if stdenv.hostPlatform.libc == "glibc" then pkgs.libc else pkgs.netbsd.getconf;
darwin = pkgs.darwin.system_cmds; darwin = pkgs.darwin.system_cmds;
# I don't see any obvious arg exec in the doc/manpage # I don't see any obvious arg exec in the doc/manpage
binlore = '' binlore = ''
@ -103,8 +103,7 @@ let
''; '';
}; };
getent = { getent = {
linux = linux = if stdenv.hostPlatform.libc == "glibc" then pkgs.libc.getent else pkgs.netbsd.getent;
if stdenv.hostPlatform.libc == "glibc" then pkgs.stdenv.cc.libc.getent else pkgs.netbsd.getent;
darwin = pkgs.netbsd.getent; darwin = pkgs.netbsd.getent;
freebsd = pkgs.freebsd.getent; freebsd = pkgs.freebsd.getent;
openbsd = pkgs.openbsd.getent; openbsd = pkgs.openbsd.getent;