From 6fdb6b54c5a9709dfc8e083b7001ac3f13f88ebf Mon Sep 17 00:00:00 2001 From: Moritz Angermann Date: Sat, 17 Oct 2026 19:40:35 +0900 Subject: [PATCH] nix: resolve Windows crypt32 import library metadata --- flake.nix | 4 +- scripts/nix/README.md | 10 ++++ scripts/nix/check-windows-crypt32.nix | 70 +++++++++++++++++++++++++++ scripts/nix/windows-crypt32.nix | 9 ++++ 4 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 scripts/nix/check-windows-crypt32.nix create mode 100644 scripts/nix/windows-crypt32.nix diff --git a/flake.nix b/flake.nix index dbb6981e79..97bcff0a4a 100644 --- a/flake.nix +++ b/flake.nix @@ -166,7 +166,9 @@ } ) - ] ++ darwinBitvec.modules ++ pkgs.lib.optional pkgs'.stdenv.hostPlatform.isWindows ({ lib, ... }: { + ] ++ darwinBitvec.modules ++ [ + (import ./scripts/nix/windows-crypt32.nix { hostPlatform = pkgs'.stdenv.hostPlatform; }) + ] ++ pkgs.lib.optional pkgs'.stdenv.hostPlatform.isWindows ({ lib, ... }: { # The preplanned local source already applies the modern patch. # Avoid applying it again after v2 source packaging. packages.crypton-x509-system.patches = lib.mkForce []; diff --git a/scripts/nix/README.md b/scripts/nix/README.md index 21252c4997..1124432805 100644 --- a/scripts/nix/README.md +++ b/scripts/nix/README.md @@ -120,6 +120,16 @@ This keeps planning and packaged Cabal metadata aligned, including the metadata used for native package unit IDs. The source producer applies the existing haskell.nix patch once; its later package patch list is empty to prevent a second application. +For this Windows GHC 9.14 package, the Nix dependency resolver also recognizes +lowercase `crypt32` as an implicit MinGW import library, matching the existing +`Crypt32` mapping. Cabal keeps the lowercase library declaration and linker flag; +all other package/library mappings stay intact. The focused resolver check uses +the real haskell.nix plan and package modules without building a compiler: + +```sh +nix eval --impure --json --file scripts/nix/check-windows-crypt32.nix \ + --apply 'test: let f = builtins.getFlake (toString ./.); in test { lib = f.inputs.haskellNix.inputs.nixpkgs.lib; haskellNix = f.inputs.haskellNix; }' +``` Linux-built Win64 `ghc914-sh` v2 projects patch only the RTS DLL search-path caller, including normal and profiling interpreters. It resolves relative paths diff --git a/scripts/nix/check-windows-crypt32.nix b/scripts/nix/check-windows-crypt32.nix new file mode 100644 index 0000000000..067aab5f95 --- /dev/null +++ b/scripts/nix/check-windows-crypt32.nix @@ -0,0 +1,70 @@ +# Exercise the actual HN plan/package/component argument fixed point. +# No source producer, toolchain, compiler, or Cabal planner is built. +{ lib, haskellNix, scenario ? "checks" }: +let + provider = builtins.toFile "crypt32-resolver-other-provider" ""; + basePkgs = { inherit lib; Crypt32 = null; otherLibrary = provider; }; + evaluate = mapping: windows: compiler: extra: lib.evalModules { + modules = [ (haskellNix + "/modules/plan.nix") (haskellNix + "/modules/error-handler.nix") { + options = { + compiler-nix-name = lib.mkOption { type = lib.types.str; default = compiler; }; + hackage.configs = lib.mkOption { type = lib.types.unspecified; default = {}; }; + hsPkgs = lib.mkOption { type = lib.types.unspecified; default = {}; }; + cabal = { + system = lib.mkOption { type = lib.types.unspecified; default = { isWindows = windows; }; }; + compiler = lib.mkOption { type = lib.types.unspecified; default = {}; }; + }; + }; + config = { + _module.args = { + pkgs = basePkgs; + pkgconfPkgs = {}; + haskellLib.types = import (haskellNix + "/lib/types.nix") { inherit lib; }; + }; + use-package-keys = false; + plan.pkg-def = _: let + revision = { pkgs, system, errorHandler, ... }: { + # Exact expression emitted for the failed crypton-x509-system plan. + components.library.libs = pkgs.lib.optional (system.isWindows) + (pkgs."crypt32" or (errorHandler.sysDepError "crypt32")) + ++ lib.optional (extra == "provided") pkgs.otherLibrary + ++ lib.optional (extra == "missing") + (pkgs.unrelated or (errorHandler.sysDepError "unrelated")); + }; + in { + compiler = { nix-name = compiler; version = "9.14.0"; packages = {}; }; + packages = { crypton-x509-system = { inherit revision; }; another-package = { inherit revision; }; }; + }; + }; + } ] ++ lib.optional mapping (import ./windows-crypt32.nix { hostPlatform.isWindows = windows; }); + }; + libs = mapping: windows: compiler: extra: + (evaluate mapping windows compiler extra).config.packages.crypton-x509-system.components.library.libs; + succeeds = value: (builtins.tryEval (builtins.deepSeq value true)).success; + disabled = windows: compiler: (lib.evalModules { + modules = [ (import ./windows-crypt32.nix { hostPlatform.isWindows = windows; }) { + options = { + compiler-nix-name = lib.mkOption { type = lib.types.str; default = compiler; }; + packages = lib.mkOption { type = lib.types.unspecified; default = {}; }; + }; + config._module.args.pkgs = throw "Disabled resolver forced its package set"; + } ]; + }).config.packages; + checks = { + oldCaseOnlyMappingRejected = !succeeds (libs false true "ghc914-sh" "none"); + lowercaseImportLibraryResolved = libs true true "ghc914-sh" "none" == []; + otherLibrariesPreserved = libs true true "ghc914-sh" "provided" == [ provider ]; + unrelatedMissingLibraryRejected = !succeeds (libs true true "ghc914-sh" "missing"); + otherPackageMappingUnchanged = !succeeds + (evaluate true true "ghc914-sh" "none").config.packages.another-package.components.library.libs; + nonWindowsUnchanged = libs true false "ghc914-sh" "provided" == [ provider ]; + otherCompilerUnchanged = !succeeds (libs true true "ghc912" "none"); + nonWindowsPackageSetLazy = disabled false "ghc914-sh" == {}; + otherCompilerPackageSetLazy = disabled true "ghc912" == {}; + }; +in +if scenario == "baseline" then libs false true "ghc914-sh" "none" +else if scenario == "unrelated" then libs true true "ghc914-sh" "missing" +else assert scenario == "checks"; +assert builtins.all (value: value) (builtins.attrValues checks); +checks diff --git a/scripts/nix/windows-crypt32.nix b/scripts/nix/windows-crypt32.nix new file mode 100644 index 0000000000..f502d47cd6 --- /dev/null +++ b/scripts/nix/windows-crypt32.nix @@ -0,0 +1,9 @@ +# The patched x509 Cabal file uses the import library's lowercase name. +# MinGW supplies crypt32 implicitly, just like HN's legacy Crypt32 alias. +{ hostPlatform }: +{ lib, pkgs, config, ... }: +lib.mkIf (hostPlatform.isWindows && config.compiler-nix-name == "ghc914-sh") { + packages.crypton-x509-system._module.args.pkgs = lib.mkForce (pkgs // { + crypt32 = null; + }); +}