From aa6fcb683a0b4c8cb5df738fe4418f4e8c2a1067 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Mon, 26 Oct 2026 00:18:04 -0400 Subject: [PATCH] threads: make it the threading package itself `threads` was `{ model, package }`, but more recently the threading packages also declare their model as `passthru.threadModel` (e.g. `mcf` for `windows.mcfgthreads`, `posix` for `windows.pthreads`). The latter technique is more idiomatic for Nixpkgs, and was done as part of the GCC NG work. Now, let's roll that out everywhere. Make `threads` just the package, or `null`, and read the model off it. - GCC "legacy": `gcc` now takes `threadsCross` as that package and derives `--enable-threads` from it, still defaulting to `win32`. - `dxvk`, because it was overriding `gcc`, is updated accordingly. - GCC NG: `gccNGPackages` no longer needs to duplicate the logic. It can just use `threads` rather than make its own. Some comments were moved around to better homes accordingly. No derivation hashes should be changed. Assisted-by: Claude Code (Claude Opus 5.5) --- pkgs/by-name/dx/dxvk/package.nix | 5 +--- pkgs/development/compilers/gcc/all.nix | 2 +- .../compilers/gcc/common/configure-flags.nix | 2 +- .../compilers/gcc/common/dependencies.nix | 4 +-- .../gcc/common/extra-target-flags.nix | 4 +-- pkgs/development/compilers/gcc/default.nix | 4 +-- .../compilers/gcc/ng/common/default.nix | 18 ++++--------- pkgs/development/compilers/go/1.26.nix | 2 +- pkgs/development/compilers/go/1.27.nix | 2 +- pkgs/os-specific/windows/default.nix | 3 +++ pkgs/top-level/all-packages.nix | 25 +++++++++++++------ 11 files changed, 35 insertions(+), 36 deletions(-) diff --git a/pkgs/by-name/dx/dxvk/package.nix b/pkgs/by-name/dx/dxvk/package.nix index 3140aa52aa57..4232507ea252 100644 --- a/pkgs/by-name/dx/dxvk/package.nix +++ b/pkgs/by-name/dx/dxvk/package.nix @@ -14,10 +14,7 @@ stdenvNoCC.mkDerivation ( overrideCC stdenv ( stdenv.cc.override (old: { cc = old.cc.override { - threadsCross = { - model = "win32"; - package = null; - }; + threadsCross = null; }; }) ); diff --git a/pkgs/development/compilers/gcc/all.nix b/pkgs/development/compilers/gcc/all.nix index e47e31a1b5f2..2901db022070 100644 --- a/pkgs/development/compilers/gcc/all.nix +++ b/pkgs/development/compilers/gcc/all.nix @@ -33,7 +33,7 @@ let reproducibleBuild = true; profiledCompiler = false; libcCross = if !buildIsTarget then targetPackages.libc or pkgs.libc else null; - threadsCross = if !buildIsTarget then targetPackages.threads or pkgs.threads else { }; + threadsCross = if !buildIsTarget then targetPackages.threads or pkgs.threads else null; isl = if stdenv.hostPlatform.isDarwin then null else isl_0_20; # do not allow version skew when cross-building gcc # diff --git a/pkgs/development/compilers/gcc/common/configure-flags.nix b/pkgs/development/compilers/gcc/common/configure-flags.nix index 6d47b52fda7e..4123b9b7e6d3 100644 --- a/pkgs/development/compilers/gcc/common/configure-flags.nix +++ b/pkgs/development/compilers/gcc/common/configure-flags.nix @@ -111,7 +111,7 @@ let if targetPlatform.isUnix then "posix" else if targetPlatform.isWindows then - (threadsCross.model or "win32") + (threadsCross.threadModel or "win32") else "single" }" diff --git a/pkgs/development/compilers/gcc/common/dependencies.nix b/pkgs/development/compilers/gcc/common/dependencies.nix index 105fac5fe094..397e256c6c97 100644 --- a/pkgs/development/compilers/gcc/common/dependencies.nix +++ b/pkgs/development/compilers/gcc/common/dependencies.nix @@ -85,7 +85,5 @@ in ++ optionals (zlib != null) [ zlib ] ++ optionals (langGo && stdenv.hostPlatform.isMusl) [ libucontext ]; - depsTargetTarget = optionals ( - !withoutTargetLibc && threadsCross != { } && threadsCross.package != null - ) [ threadsCross.package ]; + depsTargetTarget = optionals (!withoutTargetLibc && threadsCross != null) [ threadsCross ]; } diff --git a/pkgs/development/compilers/gcc/common/extra-target-flags.nix b/pkgs/development/compilers/gcc/common/extra-target-flags.nix index fa078b87ff67..665e55ffbacf 100644 --- a/pkgs/development/compilers/gcc/common/extra-target-flags.nix +++ b/pkgs/development/compilers/gcc/common/extra-target-flags.nix @@ -25,7 +25,7 @@ ); in mkFlags libcCross - ++ lib.optionals (!withoutTargetLibc) (mkFlags (threadsCross.package or null)) + ++ lib.optionals (!withoutTargetLibc) (mkFlags threadsCross) ++ mkFlags (libcCross.w32api or null); EXTRA_LDFLAGS_FOR_TARGET = @@ -50,6 +50,6 @@ ); in mkFlags libcCross - ++ lib.optionals (!withoutTargetLibc) (mkFlags (threadsCross.package or null)) + ++ lib.optionals (!withoutTargetLibc) (mkFlags threadsCross) ++ mkFlags (libcCross.w32api or null); } diff --git a/pkgs/development/compilers/gcc/default.nix b/pkgs/development/compilers/gcc/default.nix index 355b5a55d852..a78b290c953d 100644 --- a/pkgs/development/compilers/gcc/default.nix +++ b/pkgs/development/compilers/gcc/default.nix @@ -45,7 +45,7 @@ enablePlugin ? _systemInfo.buildIsHost, # Whether to support user-supplied plug-ins name ? "gcc", libcCross ? null, - threadsCross ? { }, # for MinGW + threadsCross ? null, # for MinGW withoutTargetLibc ? stdenv.targetPlatform.libc == null, flex, gnused ? null, @@ -199,7 +199,7 @@ assert langGo -> langCC; assert langAda -> gnat-bootstrap != null; # threadsCross is just for MinGW -assert threadsCross != { } -> stdenv.targetPlatform.isWindows; +assert threadsCross != null -> stdenv.targetPlatform.isWindows; # profiledCompiler builds inject non-determinism in one of the compilation stages. # If turned on, we can't provide reproducible builds anymore diff --git a/pkgs/development/compilers/gcc/ng/common/default.nix b/pkgs/development/compilers/gcc/ng/common/default.nix index 2a129f909ad7..2e6d266d513d 100644 --- a/pkgs/development/compilers/gcc/ng/common/default.nix +++ b/pkgs/development/compilers/gcc/ng/common/default.nix @@ -15,7 +15,7 @@ binutils, buildGccPackages, targetGccPackages, - windows, + threads, makeScopeWithSplicing', otherSplices, ... @@ -141,18 +141,10 @@ makeScopeWithSplicing' { }; in { - # Where the libc's own threading is not the one we want, a separate - # library supplies it: MinGW offers only `win32`, and `mcfgthreads` gives - # `mcf`, which is the better answer on Windows. `null`, the answer - # everywhere else, means "whatever the libc offers". - # The model is not written down here; the package declares it, in the - # same `passthru.threadModel` a libc uses. - # - # This stays out of the bootstrap cycle by itself: it is built with - # `windows.crossThreadsStdenv`, which on `useGccNG` platforms is stage 3 - # — real libc, bootstrap single-threaded libgcc — the very compiler that - # goes on to build the threaded `libgcc-libc`. - threads = if stdenv.hostPlatform.isMinGW then windows.mcfgthreads else null; + # See `threads` in pkgs/top-level/all-packages.nix. It is re-bound in + # this scope only to make overriding it for the other runtime libraries + # easier. + inherit threads; stdenv = overrideCC stdenv gccPackages.gcc; diff --git a/pkgs/development/compilers/go/1.26.nix b/pkgs/development/compilers/go/1.26.nix index 83f5010b9204..74efd4d9e954 100644 --- a/pkgs/development/compilers/go/1.26.nix +++ b/pkgs/development/compilers/go/1.26.nix @@ -40,7 +40,7 @@ stdenv.mkDerivation (finalAttrs: { depsBuildTarget = lib.optional isCross targetCC; - depsTargetTarget = lib.optional stdenv.targetPlatform.isMinGW targetPackages.threads.package; + depsTargetTarget = lib.optional stdenv.targetPlatform.isMinGW targetPackages.threads; postPatch = '' patchShebangs . diff --git a/pkgs/development/compilers/go/1.27.nix b/pkgs/development/compilers/go/1.27.nix index 0bdabbc7b0bb..05d99837fecd 100644 --- a/pkgs/development/compilers/go/1.27.nix +++ b/pkgs/development/compilers/go/1.27.nix @@ -40,7 +40,7 @@ stdenv.mkDerivation (finalAttrs: { depsBuildTarget = lib.optional isCross targetCC; - depsTargetTarget = lib.optional stdenv.targetPlatform.isMinGW targetPackages.threads.package; + depsTargetTarget = lib.optional stdenv.targetPlatform.isMinGW targetPackages.threads; postPatch = '' patchShebangs . diff --git a/pkgs/os-specific/windows/default.nix b/pkgs/os-specific/windows/default.nix index e125fae8a02a..b0f9dfbb9d77 100644 --- a/pkgs/os-specific/windows/default.nix +++ b/pkgs/os-specific/windows/default.nix @@ -31,6 +31,9 @@ makeScopeWithSplicing' { if stdenv.hostPlatform.useLLVM or false then buildPackages.llvmPackages.clangNoLibcxx else if stdenv.hostPlatform.useGccNG or false then + # This stage of the `gccNGPackages` bootstrap chain has a real libc + # and a bootstrap single-threaded libgcc. The threading library + # built with this is what the threaded `libgcc-libc` then links. buildPackages.gccNGPackages.gccWithLibcAndBasicLibgcc else buildPackages.gccWithoutTargetLibc.override (old: { diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index 32ea30a60841..5642ca0a9b32 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -4018,7 +4018,7 @@ with pkgs; libcxx ? null, extraPackages ? lib.optional ( cc.isGNU or false && stdenv.targetPlatform.isMinGW - ) targetPackages.threads.package, + ) targetPackages.threads, nixSupport ? { }, ... }@extraArgs: @@ -5516,14 +5516,23 @@ with pkgs; else throw "Unknown libc ${libc}"; + # An optional threading library to be used by GCC's runtime libraries. + # + # When non-null, this package will be used for that purpose. When null, libc + # will be used instead. + # + # The package (like libc, for the sake of the fallback case when this is + # null) declares its model as `passthru.threadModel`. + # + # On MinGW the libc offers only `win32`; `windows.mcfgthreads` gives `mcf`, + # and `windows.pthreads` would give `posix`. `windows.mcfgthreads` is our + # default there because it is both fast / minimally diverged from native and + # featureful. threads = - lib.optionalAttrs (stdenv.hostPlatform.isMinGW && !(stdenv.hostPlatform.useLLVM or false)) - { - # other possible values: win32 or posix - model = "mcf"; - # For win32 or posix set this to null - package = windows.mcfgthreads; - }; + if stdenv.hostPlatform.isMinGW && !(stdenv.hostPlatform.useLLVM or false) then + windows.mcfgthreads + else + null; # Only supported on Linux and only on glibc glibcLocales =