From 79aec2d4bf0bee9bae16df5cbb0be4bc2917ae16 Mon Sep 17 00:00:00 2001 From: Eman Resu <78693624+quatquatt@users.noreply.github.com> Date: Mon, 27 Apr 2026 11:02:21 -0400 Subject: [PATCH 01/14] stdenv.mkDerivation: avoid // merge if meta.mainProgram not set --- pkgs/stdenv/generic/make-derivation.nix | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/pkgs/stdenv/generic/make-derivation.nix b/pkgs/stdenv/generic/make-derivation.nix index 12a6dffb426f..f7c935168852 100644 --- a/pkgs/stdenv/generic/make-derivation.nix +++ b/pkgs/stdenv/generic/make-derivation.nix @@ -806,9 +806,7 @@ let ); let - env' = env // { - ${if meta ? mainProgram then "NIX_MAIN_PROGRAM" else null} = meta.mainProgram; - }; + env' = if meta ? mainProgram then env // { NIX_MAIN_PROGRAM = meta.mainProgram; } else env; derivationArg = makeDerivationArgument ( removeAttrs attrs [ From efa31b9d8b442e92afc0609827816110638d0b50 Mon Sep 17 00:00:00 2001 From: Eman Resu <78693624+quatquatt@users.noreply.github.com> Date: Mon, 27 Apr 2026 13:58:04 -0400 Subject: [PATCH 02/14] stdenv.mkDerivation: invert conditions, move stdenv check upwards --- pkgs/stdenv/generic/make-derivation.nix | 32 +++++++++++++------------ 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/pkgs/stdenv/generic/make-derivation.nix b/pkgs/stdenv/generic/make-derivation.nix index f7c935168852..d4493b9aaf4f 100644 --- a/pkgs/stdenv/generic/make-derivation.nix +++ b/pkgs/stdenv/generic/make-derivation.nix @@ -229,7 +229,9 @@ let canExecuteHostOnBuild = buildPlatform.canExecute hostPlatform; defaultHardeningFlags = (if stdenvHasCC then stdenv.cc else { }).defaultHardeningFlags or knownHardeningFlags; - stdenvHostSuffix = optionalString (hostPlatform != buildPlatform) "-${hostPlatform.config}"; + stdenvHostSuffix = optionalString ( + hostPlatform != buildPlatform && stdenvHasCC + ) "-${hostPlatform.config}"; stdenvStaticMarker = optionalString isStatic "-static"; userHook = config.stdenv.userHook or null; @@ -398,19 +400,6 @@ let actualValue; outputs' = outputs ++ optional separateDebugInfo' "debug"; - noNonNativeDeps = - ( - depsBuildTarget - ++ depsBuildTargetPropagated - ++ depsHostHost - ++ depsHostHostPropagated - ++ buildInputs - ++ propagatedBuildInputs - ++ depsTargetTarget - ++ depsTargetTargetPropagated - ) == [ ]; - dontAddHostSuffix = attrs ? outputHash && !noNonNativeDeps || !stdenvHasCC; - concretizeFlagImplications = flag: impliesFlags: list: if elem flag list then (list ++ impliesFlags) else list; @@ -539,7 +528,20 @@ let # suffix. But we have some weird ones with run-time deps that are # just used for their side-affects. Those might as well since the # hash can't be the same. See #32986. - hostSuffix = optionalString (!dontAddHostSuffix) stdenvHostSuffix; + hostSuffix = optionalString ( + !(attrs ? outputHash) + || + ( + depsBuildTarget + ++ depsBuildTargetPropagated + ++ depsHostHost + ++ depsHostHostPropagated + ++ buildInputs + ++ propagatedBuildInputs + ++ depsTargetTarget + ++ depsTargetTargetPropagated + ) == [ ] + ) stdenvHostSuffix; # Disambiguate statically built packages. This was originally # introduce as a means to prevent nix-env to get confused between From 9e49230e6dcc8315535b4e2c5ade12e87f6d9ab9 Mon Sep 17 00:00:00 2001 From: Eman Resu <78693624+quatquatt@users.noreply.github.com> Date: Mon, 27 Apr 2026 14:09:19 -0400 Subject: [PATCH 03/14] stdenv.mkDerivation: check if host suffix is necessary Rather than precomputing what the stdenv host suffix should be, we check the condition first. This is even better than turning the concats into multiple comparisons (although I'm going to do that as well), since if hostPlatform == buildPlatform, we never have to evaluate any further. --- pkgs/stdenv/generic/make-derivation.nix | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/pkgs/stdenv/generic/make-derivation.nix b/pkgs/stdenv/generic/make-derivation.nix index d4493b9aaf4f..101d25e5bfaf 100644 --- a/pkgs/stdenv/generic/make-derivation.nix +++ b/pkgs/stdenv/generic/make-derivation.nix @@ -229,9 +229,8 @@ let canExecuteHostOnBuild = buildPlatform.canExecute hostPlatform; defaultHardeningFlags = (if stdenvHasCC then stdenv.cc else { }).defaultHardeningFlags or knownHardeningFlags; - stdenvHostSuffix = optionalString ( - hostPlatform != buildPlatform && stdenvHasCC - ) "-${hostPlatform.config}"; + hostSuffixNecessary = hostPlatform != buildPlatform && stdenvHasCC; + stdenvHostSuffix = "-${hostPlatform.config}"; stdenvStaticMarker = optionalString isStatic "-static"; userHook = config.stdenv.userHook or null; @@ -529,8 +528,10 @@ let # just used for their side-affects. Those might as well since the # hash can't be the same. See #32986. hostSuffix = optionalString ( - !(attrs ? outputHash) - || + hostSuffixNecessary && + ( + !(attrs ? outputHash) + || ( depsBuildTarget ++ depsBuildTargetPropagated @@ -541,6 +542,7 @@ let ++ depsTargetTarget ++ depsTargetTargetPropagated ) == [ ] + ) ) stdenvHostSuffix; # Disambiguate statically built packages. This was originally From 0d2799e68b582e6655857b0394f147cc8849f88b Mon Sep 17 00:00:00 2001 From: Eman Resu <78693624+quatquatt@users.noreply.github.com> Date: Mon, 27 Apr 2026 14:19:07 -0400 Subject: [PATCH 04/14] stdenv.mkDerivation: check that build inputs are empty individually Allows short-circuiting and less concatenation. Thanks to the last commit, this is now only meaningful if `hostPlatform != buildPlatform`. --- pkgs/stdenv/generic/make-derivation.nix | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/pkgs/stdenv/generic/make-derivation.nix b/pkgs/stdenv/generic/make-derivation.nix index 101d25e5bfaf..74e819e0ec07 100644 --- a/pkgs/stdenv/generic/make-derivation.nix +++ b/pkgs/stdenv/generic/make-derivation.nix @@ -528,20 +528,19 @@ let # just used for their side-affects. Those might as well since the # hash can't be the same. See #32986. hostSuffix = optionalString ( - hostSuffixNecessary && - ( + hostSuffixNecessary + && ( !(attrs ? outputHash) || - ( - depsBuildTarget - ++ depsBuildTargetPropagated - ++ depsHostHost - ++ depsHostHostPropagated - ++ buildInputs - ++ propagatedBuildInputs - ++ depsTargetTarget - ++ depsTargetTargetPropagated - ) == [ ] + depsBuildTarget == [ ] + && depsBuildTargetPropagated == [ ] + && depsHostHost == [ ] + && depsHostHostPropagated == [ ] + && buildInputs == [ ] + && propagatedBuildInputs == [ ] + && depsTargetTarget == [ ] + && depsTargetTargetPropagated == [ ] + ) ) stdenvHostSuffix; From 0ae0cab0b834ff7b8fe56e4f2a62cfac3e15293d Mon Sep 17 00:00:00 2001 From: Eman Resu <78693624+quatquatt@users.noreply.github.com> Date: Mon, 27 Apr 2026 16:12:51 -0400 Subject: [PATCH 05/14] stdenv.mkDerivation: fallback to knownHardeningFlags directly with stdenvNoCC --- pkgs/stdenv/generic/make-derivation.nix | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pkgs/stdenv/generic/make-derivation.nix b/pkgs/stdenv/generic/make-derivation.nix index 74e819e0ec07..ed6d984d5f15 100644 --- a/pkgs/stdenv/generic/make-derivation.nix +++ b/pkgs/stdenv/generic/make-derivation.nix @@ -228,7 +228,10 @@ let canExecuteHostOnBuild = buildPlatform.canExecute hostPlatform; defaultHardeningFlags = - (if stdenvHasCC then stdenv.cc else { }).defaultHardeningFlags or knownHardeningFlags; + if stdenvHasCC then + (stdenv.cc.defaultHardeningFlags or knownHardeningFlags) + else + knownHardeningFlags; hostSuffixNecessary = hostPlatform != buildPlatform && stdenvHasCC; stdenvHostSuffix = "-${hostPlatform.config}"; stdenvStaticMarker = optionalString isStatic "-static"; From ada7d723b1957d69e6235487d359abc416229bc4 Mon Sep 17 00:00:00 2001 From: Eman Resu <78693624+quatquatt@users.noreply.github.com> Date: Sun, 26 Apr 2026 18:00:18 -0400 Subject: [PATCH 06/14] stdenv/darwin: remove no-ops --- pkgs/stdenv/darwin/default.nix | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/pkgs/stdenv/darwin/default.nix b/pkgs/stdenv/darwin/default.nix index 385a315f9c87..3cf47e5a7334 100644 --- a/pkgs/stdenv/darwin/default.nix +++ b/pkgs/stdenv/darwin/default.nix @@ -261,7 +261,6 @@ let inherit (prevStage."llvmPackages_${llvmVersion}") compiler-rt libcxx; }; llvmLibrariesDarwinDepsNoCC = prevStage: { inherit (prevStage.darwin) libcxx; }; - llvmLibrariesDeps = _: { }; llvmToolsPackages = prevStage: { inherit (prevStage."llvmPackages_${llvmVersion}") @@ -666,7 +665,6 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check assert allDeps isBuiltByBootstrapFilesCompiler [ (stage1Packages prevStage) (darwinPackages prevStage) - (llvmLibrariesDeps prevStage) (llvmToolsDeps prevStage) (sdkPackages prevStage) (sdkDarwinPackages prevStage) @@ -739,7 +737,6 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check ]; assert allDeps isBuiltByNixpkgsCompiler [ - (llvmLibrariesDeps prevStage) (llvmLibrariesPackages prevStage) ]; @@ -757,7 +754,6 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check (stage1Packages prevStage) (disallowedPackages prevStage) (bintoolsPackages prevStage) - (llvmLibrariesDeps prevStage) (llvmToolsDeps prevStage) { inherit (prevStage) ccWrapperStdenv; @@ -818,7 +814,6 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check ]; assert allDeps isBuiltByNixpkgsCompiler [ - (llvmLibrariesDeps prevStage) (llvmLibrariesPackages prevStage) (sdkPackages prevStage) (sdkDarwinPackages prevStage) @@ -837,7 +832,6 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check mergeDisjointAttrs [ (stage1Packages prevStage) (disallowedPackages prevStage) - (llvmLibrariesDeps prevStage) (sdkPackages prevStage) { inherit (prevStage) ccWrapperStdenv; @@ -894,7 +888,6 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check assert allDeps isBuiltByNixpkgsCompiler [ (bintoolsPackages prevStage) - (llvmLibrariesDeps prevStage) (llvmLibrariesPackages prevStage) (llvmToolsDeps prevStage) (llvmToolsPackages prevStage) @@ -915,7 +908,6 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check mergeDisjointAttrs [ (bintoolsPackages prevStage) (disallowedPackages prevStage) - (llvmLibrariesDeps prevStage) (llvmToolsDeps prevStage) (sdkPackages prevStage) (sdkPackagesNoCC prevStage) @@ -965,7 +957,6 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check (lib.filterAttrs (_: pkg: lib.getName pkg != "pkg-config-wrapper") (stage1Packages prevStage)) # pkg-config is a wrapper (bintoolsPackages prevStage) (darwinPackages prevStage) - (llvmLibrariesDeps prevStage) (llvmLibrariesPackages prevStage) (llvmToolsDeps prevStage) (llvmToolsPackages prevStage) @@ -1099,7 +1090,6 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check overrides = self: super: mergeDisjointAttrs [ - (llvmLibrariesDeps prevStage) (llvmToolsDeps prevStage) (sdkPackages prevStage) (sdkPackagesNoCC prevStage) From 7b8b8413eaeed0840ee56ead9143dcc383adafb6 Mon Sep 17 00:00:00 2001 From: Eman Resu <78693624+quatquatt@users.noreply.github.com> Date: Wed, 29 Apr 2026 00:41:35 -0400 Subject: [PATCH 07/14] stdenv.mkDerivation: avoid checking dependency list for empty lists --- pkgs/stdenv/generic/make-derivation.nix | 116 ++++++++++++++++-------- 1 file changed, 80 insertions(+), 36 deletions(-) diff --git a/pkgs/stdenv/generic/make-derivation.nix b/pkgs/stdenv/generic/make-derivation.nix index ed6d984d5f15..e02b6e436a68 100644 --- a/pkgs/stdenv/generic/make-derivation.nix +++ b/pkgs/stdenv/generic/make-derivation.nix @@ -468,24 +468,44 @@ let outputs = outputs'; - buildBuildOutputs = map (drv: getDev drv.__spliced.buildBuild or drv) ( - checkDependencyList "depsBuildBuild" depsBuildBuild - ); - buildHostOutputs = map (drv: getDev drv.__spliced.buildHost or drv) ( - checkDependencyList "nativeBuildInputs" nativeBuildInputs' - ); - buildTargetOutputs = map (drv: getDev drv.__spliced.buildTarget or drv) ( - checkDependencyList "depsBuildTarget" depsBuildTarget - ); - hostHostOutputs = map (drv: getDev drv.__spliced.hostHost or drv) ( - checkDependencyList "depsHostHost" depsHostHost - ); - hostTargetOutputs = map (drv: getDev drv.__spliced.hostTarget or drv) ( - checkDependencyList "buildInputs" buildInputs' - ); - targetTargetOutputs = map (drv: getDev drv.__spliced.targetTarget or drv) ( - checkDependencyList "depsTargetTarget" depsTargetTarget - ); + buildBuildOutputs = + if depsBuildBuild == [ ] then + [ ] + else + map (drv: getDev drv.__spliced.buildBuild or drv) ( + checkDependencyList "depsBuildBuild" depsBuildBuild + ); + buildHostOutputs = + if nativeBuildInputs' == [ ] then + [ ] + else + map (drv: getDev drv.__spliced.buildHost or drv) ( + checkDependencyList "nativeBuildInputs" nativeBuildInputs' + ); + buildTargetOutputs = + if depsBuildTarget == [ ] then + [ ] + else + map (drv: getDev drv.__spliced.buildTarget or drv) ( + checkDependencyList "depsBuildTarget" depsBuildTarget + ); + hostHostOutputs = + if depsHostHost == [ ] then + [ ] + else + map (drv: getDev drv.__spliced.hostHost or drv) (checkDependencyList "depsHostHost" depsHostHost); + hostTargetOutputs = + if buildInputs' == [ ] then + [ ] + else + map (drv: getDev drv.__spliced.hostTarget or drv) (checkDependencyList "buildInputs" buildInputs'); + targetTargetOutputs = + if depsTargetTarget == [ ] then + [ ] + else + map (drv: getDev drv.__spliced.targetTarget or drv) ( + checkDependencyList "depsTargetTarget" depsTargetTarget + ); allDependencies = concatLists [ buildBuildOutputs buildHostOutputs @@ -495,24 +515,48 @@ let targetTargetOutputs ]; - propagatedBuildBuildOutputs = map (drv: getDev drv.__spliced.buildBuild or drv) ( - checkDependencyList "depsBuildBuildPropagated" depsBuildBuildPropagated - ); - propagatedBuildHostOutputs = map (drv: getDev drv.__spliced.buildHost or drv) ( - checkDependencyList "propagatedNativeBuildInputs" propagatedNativeBuildInputs - ); - propagatedBuildTargetOutputs = map (drv: getDev drv.__spliced.buildTarget or drv) ( - checkDependencyList "depsBuildTargetPropagated" depsBuildTargetPropagated - ); - propagatedHostHostOutputs = map (drv: getDev drv.__spliced.hostHost or drv) ( - checkDependencyList "depsHostHostPropagated" depsHostHostPropagated - ); - propagatedHostTargetOutputs = map (drv: getDev drv.__spliced.hostTarget or drv) ( - checkDependencyList "propagatedBuildInputs" propagatedBuildInputs - ); - propagatedTargetTargetOutputs = map (drv: getDev drv.__spliced.targetTarget or drv) ( - checkDependencyList "depsTargetTargetPropagated" depsTargetTargetPropagated - ); + propagatedBuildBuildOutputs = + if depsBuildBuildPropagated == [ ] then + [ ] + else + map (drv: getDev drv.__spliced.buildBuild or drv) ( + checkDependencyList "depsBuildBuildPropagated" depsBuildBuildPropagated + ); + propagatedBuildHostOutputs = + if propagatedNativeBuildInputs == [ ] then + [ ] + else + map (drv: getDev drv.__spliced.buildHost or drv) ( + checkDependencyList "propagatedNativeBuildInputs" propagatedNativeBuildInputs + ); + propagatedBuildTargetOutputs = + if depsBuildTargetPropagated == [ ] then + [ ] + else + map (drv: getDev drv.__spliced.buildTarget or drv) ( + checkDependencyList "depsBuildTargetPropagated" depsBuildTargetPropagated + ); + propagatedHostHostOutputs = + if depsHostHostPropagated == [ ] then + [ ] + else + map (drv: getDev drv.__spliced.hostHost or drv) ( + checkDependencyList "depsHostHostPropagated" depsHostHostPropagated + ); + propagatedHostTargetOutputs = + if propagatedBuildInputs == [ ] then + [ ] + else + map (drv: getDev drv.__spliced.hostTarget or drv) ( + checkDependencyList "propagatedBuildInputs" propagatedBuildInputs + ); + propagatedTargetTargetOutputs = + if depsTargetTargetPropagated == [ ] then + [ ] + else + map (drv: getDev drv.__spliced.targetTarget or drv) ( + checkDependencyList "depsTargetTargetPropagated" depsTargetTargetPropagated + ); allPropagatedDependencies = concatLists [ propagatedBuildBuildOutputs propagatedBuildHostOutputs From ec66d5fc09695751f00f12f17347ccf76163ee43 Mon Sep 17 00:00:00 2001 From: Eman Resu <78693624+quatquatt@users.noreply.github.com> Date: Wed, 29 Apr 2026 03:21:58 -0400 Subject: [PATCH 08/14] stdenv.mkDerivation: only run fold if an invalid type or list is passed --- pkgs/stdenv/generic/make-derivation.nix | 34 ++++++++++++++++--------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/pkgs/stdenv/generic/make-derivation.nix b/pkgs/stdenv/generic/make-derivation.nix index e02b6e436a68..7f0b8c2809ad 100644 --- a/pkgs/stdenv/generic/make-derivation.nix +++ b/pkgs/stdenv/generic/make-derivation.nix @@ -13,6 +13,7 @@ stdenv: let # Lib attributes are inherited to the lexical scope for performance reasons. inherit (lib) + all assertMsg attrNames concatLists @@ -31,6 +32,7 @@ let isDerivation isInt isList + isPath isString mapAttrs mapNullable @@ -44,7 +46,6 @@ let toFunction unique zipAttrsWith - isPath seq ; @@ -226,6 +227,8 @@ let # TODO(@Ericson2314): Make always true and remove / resolve #178468 defaultStrictDeps = if config.strictDepsByDefault then true else hostPlatform != buildPlatform; + isSingularDependency = dep: dep == null || isDerivation dep || isString dep || isPath dep; + canExecuteHostOnBuild = buildPlatform.canExecute hostPlatform; defaultHardeningFlags = if stdenvHasCC then @@ -429,17 +432,24 @@ let checkDependencyList = checkDependencyList' [ ]; checkDependencyList' = positions: name: deps: - seq (foldl' ( - index: dep: - if dep == null || isDerivation dep || isString dep || isPath dep then - index + 1 - else if isList dep then - seq (checkDependencyList' ([ index ] ++ positions) name dep) (index + 1) - else - throw "Dependency is not of a valid type: ${ - concatMapStrings (ix: "element ${toString ix} of ") ([ index ] ++ positions) - }${name} for ${attrs.name or attrs.pname}" - ) 1 deps) deps; + if all isSingularDependency deps then + deps + else + # iterate again with the index if an invalid type was passed, or we + # need to recurse into a sublist. making sublists take longer is + # worth it, since nobody uses them and handling them makes normal + # dependencies slower + seq (foldl' ( + index: dep: + if isSingularDependency dep then + index + 1 + else if isList dep then + seq (checkDependencyList' ([ index ] ++ positions) name dep) (index + 1) + else + throw "Dependency is not of a valid type: ${ + concatMapStrings (ix: "element ${toString ix} of ") ([ index ] ++ positions) + }${name} for ${attrs.name or attrs.pname}" + ) 1 deps) deps; in if erroneousHardeningFlags != [ ] then abort ( From ce35986f7fa8035359a32b2c3350f875a3ad5c15 Mon Sep 17 00:00:00 2001 From: Eman Resu <78693624+quatquatt@users.noreply.github.com> Date: Wed, 29 Apr 2026 03:44:18 -0400 Subject: [PATCH 09/14] stdenv/mkDerivation: only run zipAttrsWith if we have to If attrs.outputChecks.${name} is undefined, we'd be performing an unnecessary no-op. --- pkgs/stdenv/generic/make-derivation.nix | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/pkgs/stdenv/generic/make-derivation.nix b/pkgs/stdenv/generic/make-derivation.nix index 7f0b8c2809ad..caa2e412af6e 100644 --- a/pkgs/stdenv/generic/make-derivation.nix +++ b/pkgs/stdenv/generic/make-derivation.nix @@ -784,10 +784,14 @@ let inherit name; value = let - raw = zipAttrsWith (_: concatLists) [ - attrsOutputChecksFiltered - (makeOutputChecks attrs.outputChecks.${name} or { }) - ]; + raw = + if attrs ? outputChecks.${name} then + zipAttrsWith (_: concatLists) [ + attrsOutputChecksFiltered + (makeOutputChecks attrs.outputChecks.${name}) + ] + else + attrsOutputChecksFiltered; in # separateDebugInfo = true will put all sorts of files in # the debug output which could carry references, but From ac796e9827bd4f43fc96c2e43b62645ed9bedd29 Mon Sep 17 00:00:00 2001 From: Eman Resu <78693624+quatquatt@users.noreply.github.com> Date: Sat, 9 May 2026 16:40:36 -0400 Subject: [PATCH 10/14] stdenv.mkDerivation: use or statement for default hardening flags As suggested in PR review: "It seems like when `!stdenvHasCC`, `stdenv.cc` is `null`. So this could probably just be `defaultHardeningFlags = stdenv.cc.defaultHardeningFlags or knownHardeningFlags;`?" --- pkgs/stdenv/generic/make-derivation.nix | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/pkgs/stdenv/generic/make-derivation.nix b/pkgs/stdenv/generic/make-derivation.nix index caa2e412af6e..eaa2ca0d6afc 100644 --- a/pkgs/stdenv/generic/make-derivation.nix +++ b/pkgs/stdenv/generic/make-derivation.nix @@ -230,11 +230,7 @@ let isSingularDependency = dep: dep == null || isDerivation dep || isString dep || isPath dep; canExecuteHostOnBuild = buildPlatform.canExecute hostPlatform; - defaultHardeningFlags = - if stdenvHasCC then - (stdenv.cc.defaultHardeningFlags or knownHardeningFlags) - else - knownHardeningFlags; + defaultHardeningFlags = stdenv.cc.defaultHardeningFlags or knownHardeningFlags; hostSuffixNecessary = hostPlatform != buildPlatform && stdenvHasCC; stdenvHostSuffix = "-${hostPlatform.config}"; stdenvStaticMarker = optionalString isStatic "-static"; From fde4f1c5a0583e00bee4a91efb675deb9d74785d Mon Sep 17 00:00:00 2001 From: Eman Resu <78693624+quatquatt@users.noreply.github.com> Date: Sat, 9 May 2026 18:21:20 -0400 Subject: [PATCH 11/14] stdenv.mkDerivation: check meta.mainProgram from original meta We define a meta variable in the same let block as the result of the `commonMeta` call. Avoiding evaluating the result of that call until we need to is preferable. --- pkgs/stdenv/generic/make-derivation.nix | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkgs/stdenv/generic/make-derivation.nix b/pkgs/stdenv/generic/make-derivation.nix index eaa2ca0d6afc..54282e05df77 100644 --- a/pkgs/stdenv/generic/make-derivation.nix +++ b/pkgs/stdenv/generic/make-derivation.nix @@ -866,7 +866,8 @@ let ); let - env' = if meta ? mainProgram then env // { NIX_MAIN_PROGRAM = meta.mainProgram; } else env; + env' = + if attrs ? meta.mainProgram then env // { NIX_MAIN_PROGRAM = attrs.meta.mainProgram; } else env; derivationArg = makeDerivationArgument ( removeAttrs attrs [ From 26b51ec16dd3fa98121a02da6b34a86ad0420776 Mon Sep 17 00:00:00 2001 From: Eman Resu <78693624+quatquatt@users.noreply.github.com> Date: Sat, 9 May 2026 19:11:05 -0400 Subject: [PATCH 12/14] stdenv.mkDerivation: avoid concat if separateDebugInfo' is false --- pkgs/stdenv/generic/make-derivation.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/stdenv/generic/make-derivation.nix b/pkgs/stdenv/generic/make-derivation.nix index 54282e05df77..a64b1119fead 100644 --- a/pkgs/stdenv/generic/make-derivation.nix +++ b/pkgs/stdenv/generic/make-derivation.nix @@ -399,7 +399,7 @@ let } requires __structuredAttrs if {dis,}allowedRequisites or {dis,}allowedReferences is set" else actualValue; - outputs' = outputs ++ optional separateDebugInfo' "debug"; + outputs' = if separateDebugInfo' then outputs ++ [ "debug" ] else outputs; concretizeFlagImplications = flag: impliesFlags: list: From fc43f076bbba14e7754f7f200509b95704796674 Mon Sep 17 00:00:00 2001 From: Eman Resu <78693624+quatquatt@users.noreply.github.com> Date: Sat, 9 May 2026 19:14:25 -0400 Subject: [PATCH 13/14] stdenv.mkDerivation: avoid listToAttrs if outputChecks will end up empty --- pkgs/stdenv/generic/make-derivation.nix | 68 ++++++++++++++----------- 1 file changed, 39 insertions(+), 29 deletions(-) diff --git a/pkgs/stdenv/generic/make-derivation.nix b/pkgs/stdenv/generic/make-derivation.nix index a64b1119fead..701c1a1b0c93 100644 --- a/pkgs/stdenv/generic/make-derivation.nix +++ b/pkgs/stdenv/generic/make-derivation.nix @@ -775,35 +775,45 @@ let attrsOutputChecks = makeOutputChecks attrs; attrsOutputChecksFiltered = filterAttrs (_: v: v != null) attrsOutputChecks; in - builtins.listToAttrs ( - map (name: { - inherit name; - value = - let - raw = - if attrs ? outputChecks.${name} then - zipAttrsWith (_: concatLists) [ - attrsOutputChecksFiltered - (makeOutputChecks attrs.outputChecks.${name}) - ] - else - attrsOutputChecksFiltered; - in - # separateDebugInfo = true will put all sorts of files in - # the debug output which could carry references, but - # that's "normal". Notably it symlinks to the source. - # So disable reference checking for the debug output - if separateDebugInfo' && name == "debug" then - removeAttrs raw [ - "allowedReferences" - "allowedRequisites" - "disallowedReferences" - "disallowedRequisites" - ] - else - raw; - }) outputs - ); + # to avoid the listToAttrs in most common situations, we replicate + # what it would produce for most derivations. this can be improved + # in the future at the cost of a mass rebuild - empty attrsets for + # each output is a noop + if + !attrs ? outputs + && !attrs ? outputChecks + && (attrsOutputChecks == { } || attrsOutputChecksFiltered == { }) + then + { + out = { }; + ${if separateDebugInfo' then "debug" else null} = { }; + } + else + builtins.listToAttrs ( + map (name: { + inherit name; + value = + let + raw = zipAttrsWith (_: concatLists) [ + attrsOutputChecksFiltered + (makeOutputChecks (attrs.outputChecks.${name} or { })) + ]; + in + # separateDebugInfo = true will put all sorts of files in + # the debug output which could carry references, but + # that's "normal". Notably it symlinks to the source. + # So disable reference checking for the debug output + if separateDebugInfo' && name == "debug" then + removeAttrs raw [ + "allowedReferences" + "allowedRequisites" + "disallowedReferences" + "disallowedRequisites" + ] + else + raw; + }) outputs + ); }; in derivationArg; From 152d862bb0828e191863a66c1319a83b59795932 Mon Sep 17 00:00:00 2001 From: Eman Resu <78693624+quatquatt@users.noreply.github.com> Date: Sat, 9 May 2026 19:25:03 -0400 Subject: [PATCH 14/14] stdenv.mkDerivation: cache output checks to avoid reallocating --- pkgs/stdenv/generic/make-derivation.nix | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/pkgs/stdenv/generic/make-derivation.nix b/pkgs/stdenv/generic/make-derivation.nix index 701c1a1b0c93..e6df0134b234 100644 --- a/pkgs/stdenv/generic/make-derivation.nix +++ b/pkgs/stdenv/generic/make-derivation.nix @@ -250,6 +250,14 @@ let ); gccArchFeature = [ "gccarch-${buildPlatform.gcc.arch}" ]; + cachedOutputChecks = { + out = { }; + }; + debugCachedOutputChecks = { + out = { }; + debug = { }; + }; + # Turn a derivation into its outPath without a string context attached. # See the comment at the usage site. unsafeDerivationToUntrackedOutpath = @@ -784,10 +792,7 @@ let && !attrs ? outputChecks && (attrsOutputChecks == { } || attrsOutputChecksFiltered == { }) then - { - out = { }; - ${if separateDebugInfo' then "debug" else null} = { }; - } + if separateDebugInfo' then debugCachedOutputChecks else cachedOutputChecks else builtins.listToAttrs ( map (name: {