From d278fd78af3cc0c9ccbff0ca9fbc37edb55fe97f Mon Sep 17 00:00:00 2001 From: Adam Joseph Date: Tue, 4 Jul 2023 13:09:27 -0700 Subject: [PATCH] lib.systems.extensions.sharedLibrary: do not `throw` Because downstream code expects to use `==` on platform attrsets, we are unfortunately not able to throw a useful error message when the `sharedLibrary` attribute is accessed. When users do a comparison like: stdenv.hostPlatform == pkgsStatic.stdenv.hostPlatform ... in a situation where `stdenv.hostPlatform.hasSharedLibraries`, they expect this to return `false`. Unfortunately Nix does a deep equality comparison here, and ends up forcing the `pkgsStatic.stdenv.hostPlatform.extensions.sharedLibrary` attribute, which throws the error. Rather than returning `null`, this commit instead simply omits the `extensions.sharedLibrary` attribute. This provides the user with a more-useful error message: instead of waiting until the `null` is used (and hoping that produces an error), the user will get an error about the `extensions.sharedLibrary` attribute being missing, at the position where it was referenced. Big thanks to @trofi for his PR to add `NIX_VALIDATE_EVAL_NONDETERMINISM` to Nix, which I am now using. It made tracking this down really easy! Fixes #244045 --- lib/systems/default.nix | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/systems/default.nix b/lib/systems/default.nix index a3462d2d424b..40a2c88f32b8 100644 --- a/lib/systems/default.nix +++ b/lib/systems/default.nix @@ -85,17 +85,18 @@ rec { # is why we use the more obscure "bfd" and not "binutils" for this # choice. else "bfd"; - extensions = rec { - sharedLibrary = assert final.hasSharedLibraries; - /**/ if final.isDarwin then ".dylib" + extensions = lib.optionalAttrs final.hasSharedLibraries { + sharedLibrary = + if final.isDarwin then ".dylib" else if final.isWindows then ".dll" else ".so"; + } // { staticLibrary = /**/ if final.isWindows then ".lib" else ".a"; library = - /**/ if final.isStatic then staticLibrary - else sharedLibrary; + /**/ if final.isStatic then final.extensions.staticLibrary + else final.extensions.sharedLibrary; executable = /**/ if final.isWindows then ".exe" else "";