Skip to content

Fix Windows and GHC/ucrt. #2034

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Sep 8, 2023
1 change: 1 addition & 0 deletions modules/configuration-nix.nix
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ in {
(fromUntil "3.2.0.0" "3.5" ../overlays/patches/Cabal/Cabal-3.0.0.0-no-final-checks.diff)
(fromUntil "3.6.0.0" "3.11" ../overlays/patches/Cabal/Cabal-3.6.0.0-drop-pkg-db-check.diff)
(fromUntil "3.6.0.0" "3.11" ../overlays/patches/Cabal/Cabal-3.6.0.0-no-final-checks.diff)
(fromUntil "3.10" "3.11" ../overlays/patches/Cabal/9220.patch)
];

# These two patches are:
Expand Down
13 changes: 13 additions & 0 deletions overlays/bootstrap.nix
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,18 @@ in {
++ final.lib.optionals (final.stdenv.targetPlatform.isWindows) (fromUntil "9.4.1" "9.4.5" ./patches/ghc/ghc-9.4-hadrian-win-cross.patch)
++ final.lib.optionals (final.stdenv.targetPlatform.isWindows) (fromUntil "9.4.7" "9.4.8" ./patches/ghc/ghc-9.8-hadrian-win-cross.patch)
++ final.lib.optionals (final.stdenv.targetPlatform.isWindows) (fromUntil "9.8.1" "9.10" ./patches/ghc/ghc-9.8-hadrian-win-cross.patch)
# support R_X86_64_PC64 (ELF constant 24) - IMAGE_REL_AMD64_SREL32 (PE constant 14), which seems to appear with 9.6 more frequently, and
# results in "unhandled PEi386 relocation type 14".
++ final.lib.optionals (final.stdenv.targetPlatform.isWindows) (fromUntil "9.4.1" "9.10" ./patches/ghc/win-reloc-x86_64-pc64.patch)
# ++ final.lib.optionals (final.stdenv.targetPlatform.isWindows) (fromUntil "9.4.1" "9.10" ./patches/ghc/Win32-depends-on-mingwex.patch)
# if the host system provides ucrt (e.g. wine with ucrtbase.dll), we may end up linking against symbols from ucrtbase, instead of msvcrt,
# thus leading to broken code. E.g. the handles we create and hand to wine will all be busted, because they come from one and are processed
# by another crt.
++ final.lib.optionals (final.stdenv.targetPlatform.isWindows) (fromUntil "8.10" "9.10" ./patches/ghc/win-linker-no-ucrt.patch)
# Nixos/nixpkgs is mscvrt for now, thus we must disable ucrt in ghc, otherwise we end up with broken linking.
++ final.lib.optionals (final.stdenv.targetPlatform.isWindows) (fromUntil "9.6" "9.10" ./patches/ghc/no-ucrt.patch)
# the following is needed for cardano-prelude as it uses closure_sizeW :-/
++ final.lib.optionals (final.stdenv.targetPlatform.isWindows) (fromUntil "9.6" "9.10" ./patches/ghc/win-add-closure_sizeW-to-rtssyms.patch)
++ fromUntil "9.4.5" "9.4.8" ./patches/ghc/ghc-9.4.5-include-order-fix.patch
++ fromUntil "9.6.2" "9.8" ./patches/ghc/ghc-9.4.5-include-order-fix.patch
++ fromUntil "9.6.1" "9.10" ./patches/ghc/MR10116.patch
Expand All @@ -209,6 +221,7 @@ in {
++ final.lib.optional (versionAtLeast "8.10" && versionLessThan "9.0" && final.stdenv.targetPlatform.isAarch64) ./patches/ghc/ghc-8.10-aarch64-handle-none-rela.patch
++ final.lib.optional (versionAtLeast "9.0" && final.stdenv.targetPlatform.isAarch64) ./patches/ghc/ghc-9.0-better-symbol-addr-debug.patch
++ final.lib.optional (versionAtLeast "9.0" && final.stdenv.targetPlatform.isAarch64) ./patches/ghc/ghc-9.0-aarch64-handle-none-rela.patch

;
in ({
ghc865 = final.callPackage ../compiler/ghc (traceWarnOld "8.6" {
Expand Down
70 changes: 70 additions & 0 deletions overlays/patches/Cabal/9220.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
diff --git a/src/Distribution/Simple/Configure.hs b/src/Distribution/Simple/Configure.hs
index ac7bd852f..803475283 100644
--- a/src/Distribution/Simple/Configure.hs
+++ b/src/Distribution/Simple/Configure.hs
@@ -637,22 +637,6 @@ configure (pkg_descr0, pbi) cfg = do
"--enable-split-objs; ignoring")
return False

- let compilerSupportsGhciLibs :: Bool
- compilerSupportsGhciLibs =
- case compilerId comp of
- CompilerId GHC version
- | version > mkVersion [9,3] && windows ->
- False
- CompilerId GHC _ ->
- True
- CompilerId GHCJS _ ->
- True
- _ -> False
- where
- windows = case compPlatform of
- Platform _ Windows -> True
- Platform _ _ -> False
-
let ghciLibByDefault =
case compilerId comp of
CompilerId GHC _ ->
@@ -669,15 +653,6 @@ configure (pkg_descr0, pbi) cfg = do
not (GHCJS.isDynamic comp)
_ -> False

- withGHCiLib_ <-
- case fromFlagOrDefault ghciLibByDefault (configGHCiLib cfg) of
- True | not compilerSupportsGhciLibs -> do
- warn verbosity $
- "--enable-library-for-ghci is no longer supported on Windows with"
- ++ " GHC 9.4 and later; ignoring..."
- return False
- v -> return v
-
let sharedLibsByDefault
| fromFlag (configDynExe cfg) =
-- build a shared library if dynamically-linked
@@ -774,7 +749,7 @@ configure (pkg_descr0, pbi) cfg = do
withProfExeDetail = ProfDetailNone,
withOptimization = fromFlag $ configOptimization cfg,
withDebugInfo = fromFlag $ configDebugInfo cfg,
- withGHCiLib = withGHCiLib_,
+ withGHCiLib = fromFlagOrDefault ghciLibByDefault (configGHCiLib cfg),
splitSections = split_sections,
splitObjs = split_objs,
stripExes = strip_exe,
diff --git a/src/Distribution/Simple/Setup.hs b/src/Distribution/Simple/Setup.hs
index 36f6aa22f..aa60b73b8 100644
--- a/src/Distribution/Simple/Setup.hs
+++ b/src/Distribution/Simple/Setup.hs
@@ -384,12 +384,7 @@ defaultConfigFlags progDb = emptyConfigFlags {
configCabalFilePath = NoFlag,
configVerbosity = Flag normal,
configUserInstall = Flag False, --TODO: reverse this
-#if defined(mingw32_HOST_OS)
- -- See #8062 and GHC #21019.
- configGHCiLib = Flag False,
-#else
- configGHCiLib = NoFlag,
-#endif
+ configGHCiLib = Flag True,
configSplitSections = Flag False,
configSplitObjs = Flag False, -- takes longer, so turn off by default
configStripExes = NoFlag,
13 changes: 13 additions & 0 deletions overlays/patches/ghc/Win32-depends-on-mingwex.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
diff --git a/libraries/Win32/Win32.cabal b/libraries/Win32/Win32.cabal
index e986b7e..603354f 100644
--- a/libraries/Win32/Win32.cabal
+++ b/libraries/Win32/Win32.cabal
@@ -138,7 +138,7 @@ Library
System.Win32.Time.Internal

extra-libraries:
- "user32", "gdi32", "winmm", "advapi32", "shell32", "shfolder", "shlwapi", "msimg32", "imm32"
+ "user32", "gdi32", "winmm", "advapi32", "shell32", "shfolder", "shlwapi", "msimg32", "imm32", "mingwex"
ghc-options: -Wall
include-dirs: include
includes: "alphablend.h", "diatemp.h", "dumpBMP.h", "ellipse.h", "errors.h", "HsGDI.h", "HsWin32.h", "Win32Aux.h", "win32debug.h", "windows_cconv.h", "WndProc.h", "alignment.h"
26 changes: 26 additions & 0 deletions overlays/patches/ghc/no-ucrt.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
diff --git a/libraries/ghc-prim/ghc-prim.cabal b/libraries/ghc-prim/ghc-prim.cabal
index 5393363..4f5db98 100644
--- a/libraries/ghc-prim/ghc-prim.cabal
+++ b/libraries/ghc-prim/ghc-prim.cabal
@@ -73,7 +73,7 @@ Library
-- mingw32 which is required by mingwex.
-- user32: provides access to apis to modify user components (UI etc)
-- on Windows. Required because of mingw32.
- extra-libraries: user32, mingw32, ucrt
+ extra-libraries: user32, mingw32, msvcrt, mingwex

if os(linux)
-- we need libm, but for musl and other's we might need libc, as libm
diff --git a/m4/fp_setup_windows_toolchain.m4 b/m4/fp_setup_windows_toolchain.m4
index 1f44a38..122a205 100644
--- a/m4/fp_setup_windows_toolchain.m4
+++ b/m4/fp_setup_windows_toolchain.m4
@@ -86,7 +86,7 @@ AC_DEFUN([FP_SETUP_WINDOWS_TOOLCHAIN],[
# Signal that we are linking against UCRT with the _UCRT macro. This is
# necessary to ensure correct behavior when MinGW-w64 headers are in the
# header include path (#22159).
- cflags="--rtlib=compiler-rt -D_UCRT"
+ cflags=""
CFLAGS="$cflags"
CONF_CC_OPTS_STAGE1="$cflags"
CONF_CC_OPTS_STAGE2="$cflags"
15 changes: 15 additions & 0 deletions overlays/patches/ghc/win-add-closure_sizeW-to-rtssyms.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
diff --git a/rts/RtsSymbols.c b/rts/RtsSymbols.c
index 10efb2a..d8ea070 100644
--- a/rts/RtsSymbols.c
+++ b/rts/RtsSymbols.c
@@ -160,7 +160,9 @@ extern char **environ;
SymI_HasProto(__mingw_vsnwprintf) \
/* ^^ Need to figure out why this is needed. */ \
SymI_HasProto(__mingw_vfprintf) \
- /* ^^ Need to figure out why this is needed. */
+ /* ^^ Need to figure out why this is needed. */ \
+ SymI_HasProto(closure_sizeW_) \
+ /* ^^ This one needed for cardano-prelude m( */
#else
#define RTS_MINGW_ONLY_SYMBOLS /**/
#endif
16 changes: 16 additions & 0 deletions overlays/patches/ghc/win-linker-no-ucrt.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
diff --git a/rts/linker/PEi386.c b/rts/linker/PEi386.c
index c404992..fd060e4 100644
--- a/rts/linker/PEi386.c
+++ b/rts/linker/PEi386.c
@@ -1132,6 +1132,11 @@ lookupSymbolInDLLs ( const SymbolName* lbl, ObjectCode *dependent )
for (o_dll = opened_dlls; o_dll != NULL; o_dll = o_dll->next) {
/* debugBelch("look in %ls for %s\n", o_dll->name, lbl); */

+ if (wcsncmp(o_dll->name,WSTR("ucrtbase.dll"),wcslen(WSTR("ucrtbase.dll"))) == 0) {
+ IF_DEBUG(linker, debugBelch("warning: ignoring %s\n", o_dll->name));
+ continue;
+ }
+
sym = GetProcAddress(o_dll->instance, lbl+STRIP_LEADING_UNDERSCORE);
if (sym != NULL) {
/*debugBelch("found %s in %s\n", lbl+1,o_dll->name);*/
20 changes: 20 additions & 0 deletions overlays/patches/ghc/win-reloc-x86_64-pc64.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
diff --git a/rts/linker/PEi386.c b/rts/linker/PEi386.c
index 0b328df..c404992 100644
--- a/rts/linker/PEi386.c
+++ b/rts/linker/PEi386.c
@@ -2071,6 +2071,15 @@ ocResolve_PEi386 ( ObjectCode* oc )
*(uint32_t *)pP = (uint32_t)v;
break;
}
+ case 14: /* R_X86_64_PC64 (ELF constant 24) - IMAGE_REL_AMD64_SREL32 (PE constant 14) */
+ {
+ /* mingw will emit this for a pc-rel 64 relocation */
+ uint64_t A;
+ checkProddableBlock(oc, pP, 8);
+ A = *(uint64_t*)pP;
+ *(uint64_t *)pP = S + A - (intptr_t)pP;
+ break;
+ }
case 4: /* R_X86_64_PC32 (ELF constant 2) - IMAGE_REL_AMD64_REL32 (PE constant 4) */
{
intptr_t v;
13 changes: 13 additions & 0 deletions overlays/patches/wine-add-dll-directory.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c
index 85eb2976807..36d92b32d1c 100644
--- a/dlls/ntdll/loader.c
+++ b/dlls/ntdll/loader.c
@@ -4015,7 +4015,7 @@ NTSTATUS WINAPI LdrAddDllDirectory( const UNICODE_STRING *dir, void **cookie )
struct dll_dir_entry *ptr;
DOS_PATHNAME_TYPE type = RtlDetermineDosPathNameType_U( dir->Buffer );

- if (type != ABSOLUTE_PATH && type != ABSOLUTE_DRIVE_PATH)
+ if (type != ABSOLUTE_PATH && type != ABSOLUTE_DRIVE_PATH && type != DEVICE_PATH )
return STATUS_INVALID_PARAMETER;

status = RtlDosPathNameToNtPathName_U_WithStatus( dir->Buffer, &nt_name, NULL, NULL );
23 changes: 6 additions & 17 deletions overlays/wine.nix
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,10 @@
# files from TH code) for GHC built with msvcrt (ghc<9.6).
# This will inevitably replace *any* wine version. Thus this might not really be what we ultimately want.
# Wine 5.4 does not build on macOS so that is not pinned and TH code will probably break.
final: prev:
prev.lib.optionalAttrs (!prev.stdenv.hostPlatform.isDarwin) {
winePackages = prev.winePackages // {
minimal = prev.winePackages.minimal.overrideAttrs (oldAttrs: {
name = "wine-5.4";
version = "5.4";
src = prev.fetchurl {
url = "https://dl.winehq.org/wine/source/5.x/wine-5.4.tar.xz";
sha256 = "sha256-Sz4rD/pUFfGZVA5gUcKMOXb86R6lv7LPSgmcJXMXBSw=";
};
patches = [];
# Turning off the tests as there is a problem with the `schedsvc` test.
# With recent nixpkgs both the IDL files generate `_c.c` files with
# `handle_t rpc_handle` and that results in a linker error (duplicate symbols).
configureFlags = oldAttrs.configureFlags or [] ++ ["--disable-tests"];
});
};
final: prev: {
winePackages = prev.winePackages // {
minimal = prev.winePackages.minimal.overrideAttrs (oldAttrs: {
patches = oldAttrs.patches or [] ++ [ ./patches/wine-add-dll-directory.patch ];
});
};
}