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
This commit is contained in:
Adam Joseph 2023-07-04 13:09:27 -07:00
parent 083a9cb41f
commit d278fd78af

View File

@ -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 "";