From 22403802b0c3ded4178e7b5f91126a42f9d26288 Mon Sep 17 00:00:00 2001 From: Sylvain Henry Date: Wed, 24 Sep 2025 15:47:11 +0200 Subject: [PATCH 1/5] Fix PIC jump tables on Windows (#24016) Avoid overflows in jump tables by using a base label closer to the jump targets. See added Note [Jump tables] --- compiler/GHC/CmmToAsm/X86/CodeGen.hs | 193 ++++++++++-------- compiler/GHC/CmmToAsm/X86/Instr.hs | 25 +-- compiler/GHC/CmmToAsm/X86/Ppr.hs | 2 +- docs/users_guide/phases.rst | 11 +- testsuite/tests/codeGen/should_run/T24016.hs | 24 +++ .../tests/codeGen/should_run/T24016.stdout | 1 + testsuite/tests/codeGen/should_run/all.T | 1 + 7 files changed, 156 insertions(+), 101 deletions(-) create mode 100644 testsuite/tests/codeGen/should_run/T24016.hs create mode 100644 testsuite/tests/codeGen/should_run/T24016.stdout diff --git a/compiler/GHC/CmmToAsm/X86/CodeGen.hs b/compiler/GHC/CmmToAsm/X86/CodeGen.hs index c65a0914387c..c4844baaa2d2 100644 --- a/compiler/GHC/CmmToAsm/X86/CodeGen.hs +++ b/compiler/GHC/CmmToAsm/X86/CodeGen.hs @@ -374,7 +374,7 @@ stmtToInstrs bid stmt = do --We try to arrange blocks such that the likely branch is the fallthrough --in GHC.Cmm.ContFlowOpt. So we can assume the condition is likely false here. CmmCondBranch arg true false _ -> genCondBranch bid true false arg - CmmSwitch arg ids -> genSwitch arg ids + CmmSwitch arg ids -> genSwitch arg ids bid CmmCall { cml_target = arg , cml_args_regs = gregs } -> genJump arg (jumpRegs platform gregs) _ -> @@ -487,13 +487,6 @@ is32BitInteger i = i64 <= 0x7fffffff && i64 >= -0x80000000 where i64 = fromIntegral i :: Int64 --- | Convert a BlockId to some CmmStatic data -jumpTableEntry :: NCGConfig -> Maybe BlockId -> CmmStatic -jumpTableEntry config Nothing = CmmStaticLit (CmmInt 0 (ncgWordWidth config)) -jumpTableEntry _ (Just blockid) = CmmStaticLit (CmmLabel blockLabel) - where blockLabel = blockLbl blockid - - -- ----------------------------------------------------------------------------- -- General things for putting together code sequences @@ -5337,11 +5330,52 @@ index (1), indexExpr = UU_Conv(indexOffset); // == 1::I64 See #21186. --} -genSwitch :: CmmExpr -> SwitchTargets -> NatM InstrBlock +Note [Jump tables] +~~~~~~~~~~~~~~~~~~ +The x86 backend has a virtual JMP_TBL instruction which payload can be used to +generate both the jump instruction and the jump table contents. `genSwitch` is +responsible for generating these JMP_TBL instructions. + +Depending on `-fPIC` flag and on the architecture, we generate the following +jump table variants: + + | Variant | Arch | Table's contents | Reference to the table | + |---------|--------|----------------------------------------|------------------------| + | PIC | Both | Relative offset: target_lbl - base_lbl | PIC | + | Non-PIC | 64-bit | Absolute: target_lbl | Non-PIC (rip-relative) | + | Non-PIC | 32-bit | Absolute: target_lbl | Non-PIC (absolute) | + +For the PIC variant, we store relative entries (`target_lbl - base_lbl`) in the +jump table. Using absolute entries with PIC would require target_lbl symbols to +be resolved at link time, hence to be global labels (currently they are local +labels). + +We use the block_id of the code containing the jump as `base_lbl`. It ensures +that target_lbl and base_lbl are close enough to each others, avoiding +overflows. + +Historical note: in the past we used the table label `table_lbl` as base_lbl. It +allowed the jumping code to only compute one global address (table_lbl) both to +read the table and to compute the target address. However: -genSwitch expr targets = do + * the table could be too far from the jump and on Windows which only + has 32-bit relative relocations (IMAGE_REL_AMD64_REL64 doesn't exist), + `dest_lbl - table_lbl` overflowed (see #24016) + + * Mac OS X/x86-64 linker was unable to handle `.quad L1 - L0` + relocations if L0 wasn't preceded by a non-anonymous label in its + section (which was the case with table_lbl). Hence we used to put the + jump table in the .text section in this case. + + +-} + +-- | Generate a JMP_TBL instruction +-- +-- See Note [Jump tables] +genSwitch :: CmmExpr -> SwitchTargets -> BlockId -> NatM InstrBlock +genSwitch expr targets bid = do config <- getConfig let platform = ncgPlatform config expr_w = cmmExprWidth platform expr @@ -5352,79 +5386,76 @@ genSwitch expr targets = do indexExpr = CmmMachOp (MO_UU_Conv expr_w (platformWordWidth platform)) [indexExpr0] - if ncgPIC config - then do - (reg,e_code) <- getNonClobberedReg indexExpr - -- getNonClobberedReg because it needs to survive across t_code - lbl <- getNewLabelNat - let is32bit = target32Bit platform - os = platformOS platform - -- Might want to use .rodata. instead, but as - -- long as it's something unique it'll work out since the - -- references to the jump table are in the appropriate section. - rosection = case os of - -- on Mac OS X/x86_64, put the jump table in the text section to - -- work around a limitation of the linker. - -- ld64 is unable to handle the relocations for - -- .quad L1 - L0 - -- if L0 is not preceded by a non-anonymous label in its section. - OSDarwin | not is32bit -> Section Text lbl - _ -> Section ReadOnlyData lbl - dynRef <- cmmMakeDynamicReference config DataReference lbl - (tableReg,t_code) <- getSomeReg $ dynRef - let op = OpAddr (AddrBaseIndex (EABaseReg tableReg) - (EAIndex reg (platformWordSizeInBytes platform)) (ImmInt 0)) - - return $ e_code `appOL` t_code `appOL` toOL [ - ADD (intFormat (platformWordWidth platform)) op (OpReg tableReg), - JMP_TBL (OpReg tableReg) ids rosection lbl - ] - else do - (reg,e_code) <- getSomeReg indexExpr - lbl <- getNewLabelNat - let is32bit = target32Bit platform - if is32bit - then let op = OpAddr (AddrBaseIndex EABaseNone (EAIndex reg (platformWordSizeInBytes platform)) (ImmCLbl lbl)) - jmp_code = JMP_TBL op ids (Section ReadOnlyData lbl) lbl - in return $ e_code `appOL` unitOL jmp_code - else do + + (offset, blockIds) = switchTargetsToTable targets + ids = map (fmap DestBlockId) blockIds + + is32bit = target32Bit platform + fmt = archWordFormat is32bit + + table_lbl <- getNewLabelNat + let bid_lbl = blockLbl bid + let table_section = Section ReadOnlyData table_lbl + + -- see Note [Jump tables] for a description of the following 3 variants. + if + | ncgPIC config -> do + -- PIC support: store relative offsets in the jump table to allow the code + -- to be relocated without updating the table. The table itself and the + -- block label used to make the relative labels absolute are read in a PIC + -- way (via cmmMakeDynamicReference). + (reg,e_code) <- getNonClobberedReg indexExpr -- getNonClobberedReg because it needs to survive across t_code and j_code + (tableReg,t_code) <- getNonClobberedReg =<< cmmMakeDynamicReference config DataReference table_lbl + (targetReg,j_code) <- getSomeReg =<< cmmMakeDynamicReference config DataReference bid_lbl + pure $ e_code `appOL` t_code `appOL` j_code `appOL` toOL + [ ADD fmt (OpAddr (AddrBaseIndex (EABaseReg tableReg) (EAIndex reg (platformWordSizeInBytes platform)) (ImmInt 0))) + (OpReg targetReg) + , JMP_TBL (OpReg targetReg) ids table_section table_lbl (Just bid_lbl) + ] + + | not is32bit -> do + -- 64-bit non-PIC code + (reg,e_code) <- getSomeReg indexExpr + tableReg <- getNewRegNat (intFormat (platformWordWidth platform)) + targetReg <- getNewRegNat (intFormat (platformWordWidth platform)) + pure $ e_code `appOL` toOL -- See Note [%rip-relative addressing on x86-64]. - tableReg <- getNewRegNat (intFormat (platformWordWidth platform)) - targetReg <- getNewRegNat (intFormat (platformWordWidth platform)) - let op = OpAddr (AddrBaseIndex (EABaseReg tableReg) (EAIndex reg (platformWordSizeInBytes platform)) (ImmInt 0)) - fmt = archWordFormat is32bit - code = e_code `appOL` toOL - [ LEA fmt (OpAddr (AddrBaseIndex EABaseRip EAIndexNone (ImmCLbl lbl))) (OpReg tableReg) - , MOV fmt op (OpReg targetReg) - , JMP_TBL (OpReg targetReg) ids (Section ReadOnlyData lbl) lbl - ] - return code - where - (offset, blockIds) = switchTargetsToTable targets - ids = map (fmap DestBlockId) blockIds + [ LEA fmt (OpAddr (AddrBaseIndex EABaseRip EAIndexNone (ImmCLbl table_lbl))) (OpReg tableReg) + , MOV fmt (OpAddr (AddrBaseIndex (EABaseReg tableReg) (EAIndex reg (platformWordSizeInBytes platform)) (ImmInt 0))) + (OpReg targetReg) + , JMP_TBL (OpReg targetReg) ids table_section table_lbl Nothing + ] + + | otherwise -> do + -- 32-bit non-PIC code is a straightforward jump to &table[entry]. + (reg,e_code) <- getSomeReg indexExpr + pure $ e_code `appOL` unitOL + ( JMP_TBL (OpAddr (AddrBaseIndex EABaseNone (EAIndex reg (platformWordSizeInBytes platform)) (ImmCLbl table_lbl))) + ids table_section table_lbl Nothing + ) generateJumpTableForInstr :: NCGConfig -> Instr -> Maybe (NatCmmDecl (Alignment, RawCmmStatics) Instr) -generateJumpTableForInstr config (JMP_TBL _ ids section lbl) - = let getBlockId (DestBlockId id) = id - getBlockId _ = panic "Non-Label target in Jump Table" - blockIds = map (fmap getBlockId) ids - in Just (createJumpTable config blockIds section lbl) -generateJumpTableForInstr _ _ = Nothing - -createJumpTable :: NCGConfig -> [Maybe BlockId] -> Section -> CLabel - -> GenCmmDecl (Alignment, RawCmmStatics) h g -createJumpTable config ids section lbl - = let jumpTable - | ncgPIC config = - let ww = ncgWordWidth config - jumpTableEntryRel Nothing - = CmmStaticLit (CmmInt 0 ww) - jumpTableEntryRel (Just blockid) - = CmmStaticLit (CmmLabelDiffOff blockLabel lbl 0 ww) - where blockLabel = blockLbl blockid - in map jumpTableEntryRel ids - | otherwise = map (jumpTableEntry config) ids - in CmmData section (mkAlignment 1, CmmStaticsRaw lbl jumpTable) +generateJumpTableForInstr config = \case + JMP_TBL _ ids section table_lbl mrel_lbl -> + let getBlockId (DestBlockId id) = id + getBlockId _ = panic "Non-Label target in Jump Table" + block_ids = map (fmap getBlockId) ids + + jumpTable = case mrel_lbl of + Nothing -> map mk_absolute block_ids -- absolute entries + Just rel_lbl -> map (mk_relative rel_lbl) block_ids -- offsets relative to rel_lbl + + mk_absolute = \case + Nothing -> CmmStaticLit (CmmInt 0 (ncgWordWidth config)) + Just blockid -> CmmStaticLit (CmmLabel (blockLbl blockid)) + + mk_relative rel_lbl = \case + Nothing -> CmmStaticLit (CmmInt 0 (ncgWordWidth config)) + Just blockid -> CmmStaticLit (CmmLabelDiffOff (blockLbl blockid) rel_lbl 0 (ncgWordWidth config)) + + in Just (CmmData section (mkAlignment 1, CmmStaticsRaw table_lbl jumpTable)) + + _ -> Nothing extractUnwindPoints :: [Instr] -> [UnwindPoint] extractUnwindPoints instrs = diff --git a/compiler/GHC/CmmToAsm/X86/Instr.hs b/compiler/GHC/CmmToAsm/X86/Instr.hs index 3a7939a58049..44bf1ed39c22 100644 --- a/compiler/GHC/CmmToAsm/X86/Instr.hs +++ b/compiler/GHC/CmmToAsm/X86/Instr.hs @@ -250,6 +250,7 @@ data Instr [Maybe JumpDest] -- Targets of the jump table Section -- Data section jump table should be put in CLabel -- Label of jump table + !(Maybe CLabel) -- Label used to compute relative offsets. Otherwise we store absolute addresses. -- | X86 call instruction | CALL (Either Imm Reg) -- ^ Jump target [RegWithFormat] -- ^ Arguments (required for register allocation) @@ -476,7 +477,7 @@ regUsageOfInstr platform instr JXX _ _ -> mkRU [] [] JXX_GBL _ _ -> mkRU [] [] JMP op regs -> mkRU (use_R addrFmt op regs) [] - JMP_TBL op _ _ _ -> mkRU (use_R addrFmt op []) [] + JMP_TBL op _ _ _ _ -> mkRU (use_R addrFmt op []) [] CALL (Left _) params -> mkRU params (map mkFmt $ callClobberedRegs platform) CALL (Right reg) params -> mkRU (mk addrFmt reg:params) (map mkFmt $ callClobberedRegs platform) CLTD fmt -> mkRU [mk fmt eax] [mk fmt edx] @@ -795,7 +796,7 @@ patchRegsOfInstr platform instr env POP fmt op -> patch1 (POP fmt) op SETCC cond op -> patch1 (SETCC cond) op JMP op regs -> JMP (patchOp op) regs - JMP_TBL op ids s lbl -> JMP_TBL (patchOp op) ids s lbl + JMP_TBL op ids s tl jl -> JMP_TBL (patchOp op) ids s tl jl FMA3 fmt perm var x1 x2 x3 -> patch3 (FMA3 fmt perm var) x1 x2 x3 @@ -997,9 +998,9 @@ isJumpishInstr instr canFallthroughTo :: Instr -> BlockId -> Bool canFallthroughTo insn bid = case insn of - JXX _ target -> bid == target - JMP_TBL _ targets _ _ -> all isTargetBid targets - _ -> False + JXX _ target -> bid == target + JMP_TBL _ targets _ _ _ -> all isTargetBid targets + _ -> False where isTargetBid target = case target of Nothing -> True @@ -1012,9 +1013,9 @@ jumpDestsOfInstr jumpDestsOfInstr insn = case insn of - JXX _ id -> [id] - JMP_TBL _ ids _ _ -> [id | Just (DestBlockId id) <- ids] - _ -> [] + JXX _ id -> [id] + JMP_TBL _ ids _ _ _ -> [id | Just (DestBlockId id) <- ids] + _ -> [] patchJumpInstr @@ -1023,8 +1024,8 @@ patchJumpInstr patchJumpInstr insn patchF = case insn of JXX cc id -> JXX cc (patchF id) - JMP_TBL op ids section lbl - -> JMP_TBL op (map (fmap (patchJumpDest patchF)) ids) section lbl + JMP_TBL op ids section table_lbl rel_lbl + -> JMP_TBL op (map (fmap (patchJumpDest patchF)) ids) section table_lbl rel_lbl _ -> insn where patchJumpDest f (DestBlockId id) = DestBlockId (f id) @@ -1485,14 +1486,14 @@ shortcutJump fn insn = shortcutJump' fn (setEmpty :: LabelSet) insn Just (DestBlockId id') -> shortcutJump' fn seen' (JXX cc id') Just (DestImm imm) -> shortcutJump' fn seen' (JXX_GBL cc imm) where seen' = setInsert id seen - shortcutJump' fn _ (JMP_TBL addr blocks section tblId) = + shortcutJump' fn _ (JMP_TBL addr blocks section table_lbl rel_lbl) = let updateBlock (Just (DestBlockId bid)) = case fn bid of Nothing -> Just (DestBlockId bid ) Just dest -> Just dest updateBlock dest = dest blocks' = map updateBlock blocks - in JMP_TBL addr blocks' section tblId + in JMP_TBL addr blocks' section table_lbl rel_lbl shortcutJump' _ _ other = other -- Here because it knows about JumpDest diff --git a/compiler/GHC/CmmToAsm/X86/Ppr.hs b/compiler/GHC/CmmToAsm/X86/Ppr.hs index df4262f02ca3..8a6208332997 100644 --- a/compiler/GHC/CmmToAsm/X86/Ppr.hs +++ b/compiler/GHC/CmmToAsm/X86/Ppr.hs @@ -889,7 +889,7 @@ pprInstr platform i = case i of JMP op _ -> line $ text "\tjmp *" <> pprOperand platform (archWordFormat (target32Bit platform)) op - JMP_TBL op _ _ _ + JMP_TBL op _ _ _ _ -> pprInstr platform (JMP op []) CALL (Left imm) _ diff --git a/docs/users_guide/phases.rst b/docs/users_guide/phases.rst index 3a01cdb3d856..8eb56f99abf4 100644 --- a/docs/users_guide/phases.rst +++ b/docs/users_guide/phases.rst @@ -770,10 +770,9 @@ Options affecting code generation :type: dynamic :category: codegen - Generate position-independent code (code that can be put into shared - libraries). This currently works on Linux x86 and x86-64. On - Windows, position-independent code is never used so the flag is a - no-op on that platform. + Generate position-independent code (PIC). This code can be put into shared + libraries and is sometimes required by operating systems, e.g. systems using + Address Space Layout Randomization (ASLR). .. ghc-flag:: -fexternal-dynamic-refs :shortdesc: Generate code for linking against dynamic libraries @@ -790,9 +789,7 @@ Options affecting code generation :category: codegen Generate code in such a way to be linkable into a position-independent - executable This currently works on Linux x86 and x86-64. On Windows, - position-independent code is never used so the flag is a no-op on that - platform. To link the final executable use :ghc-flag:`-pie`. + executable. To link the final executable use :ghc-flag:`-pie`. .. ghc-flag:: -dynamic :shortdesc: Build dynamically-linked object files and executables diff --git a/testsuite/tests/codeGen/should_run/T24016.hs b/testsuite/tests/codeGen/should_run/T24016.hs new file mode 100644 index 000000000000..d56dfb720c80 --- /dev/null +++ b/testsuite/tests/codeGen/should_run/T24016.hs @@ -0,0 +1,24 @@ +module Main (main) where + +data Command + = Command1 + | Command2 + | Command3 + | Command4 + | Command5 + | Command6 -- Commenting this line works with -fPIC, uncommenting leads to a crash. + +main :: IO () +main = do + let x = case cmd of + Command1 -> 1 :: Int + Command2 -> 2 + Command3 -> 3 + Command4 -> 4 + Command5 -> 5 + Command6 -> 6 + putStrLn (show x) + +{-# NOINLINE cmd #-} +cmd :: Command +cmd = Command6 diff --git a/testsuite/tests/codeGen/should_run/T24016.stdout b/testsuite/tests/codeGen/should_run/T24016.stdout new file mode 100644 index 000000000000..1e8b31496214 --- /dev/null +++ b/testsuite/tests/codeGen/should_run/T24016.stdout @@ -0,0 +1 @@ +6 diff --git a/testsuite/tests/codeGen/should_run/all.T b/testsuite/tests/codeGen/should_run/all.T index 7f37271f79a8..e96437957245 100644 --- a/testsuite/tests/codeGen/should_run/all.T +++ b/testsuite/tests/codeGen/should_run/all.T @@ -256,3 +256,4 @@ test('T24893', normal, compile_and_run, ['-O']) test('CCallConv', [req_c], compile_and_run, ['CCallConv_c.c']) test('T25364', normal, compile_and_run, ['']) test('T26061', normal, compile_and_run, ['']) +test('T24016', normal, compile_and_run, ['-O1 -fPIC']) From 914c01b857c9af3c9f8e3f1073452aef227e271b Mon Sep 17 00:00:00 2001 From: Julian Ospald Date: Thu, 20 Nov 2025 16:06:35 +0800 Subject: [PATCH 2/5] Snippidy-snip, windows is lit --- Makefile | 57 +++++++++++-------- cabal.project.stage2 | 24 +++++++- cabal.project.stage3 | 15 +++++ compiler/GHC/SysTools/BaseDir.hs | 23 -------- libraries/Cabal | 2 +- libraries/ghc-internal/configure.ac | 3 +- .../src/GHC/Internal/IO/Windows/Paths.hs | 2 +- rts/RtsSymbols.c | 3 + 8 files changed, 76 insertions(+), 53 deletions(-) diff --git a/Makefile b/Makefile index 65aa7aff1086..d485a39766e1 100644 --- a/Makefile +++ b/Makefile @@ -104,6 +104,14 @@ SED ?= sed LD ?= ld +ifeq ($(OS),Windows_NT) +CC := clang.exe +CXX := clang++.exe +CYGPATH = cygpath --unix -f - +else +CYGPATH = echo +endif + EMCC ?= emcc EMCXX ?= em++ EMAR ?= emar @@ -251,7 +259,6 @@ STAGE2_UTIL_TARGETS := \ ghc-toolchain:ghc-toolchain \ integer-gmp:integer-gmp \ system-cxx-std-lib:system-cxx-std-lib \ - terminfo:terminfo \ xhtml:xhtml # These things should be built on demand. @@ -560,7 +567,7 @@ _build/stage0/bin/cabal: @echo "::group::Building Cabal..." @mkdir -p _build/stage0/bin _build/logs cabal build $(BUILD_ARGS) cabal-install:exe:cabal - cp -rfp $(shell cabal list-bin -v0 $(BUILD_ARGS) cabal-install:exe:cabal) _build/stage0/bin/cabal + cp -rfp $(shell cabal list-bin -v0 $(BUILD_ARGS) cabal-install:exe:cabal | $(CYGPATH)) _build/stage0/bin/cabal @echo "::endgroup::" # --- Stage 1 build --- @@ -618,8 +625,8 @@ $(addprefix _build/stage2/bin/,$(STAGE2_EXECUTABLES)) &: $(CABAL) stage1 @echo "::group::Building stage2 executables ($(STAGE2_EXECUTABLES))..." # Force cabal to replan rm -rf _build/stage2/cache - HADRIAN_SETTINGS='$(HADRIAN_SETTINGS)' \ - PATH=$(PWD)/_build/stage1/bin:$(PATH) \ + GHC=$(GHC) HADRIAN_SETTINGS='$(HADRIAN_SETTINGS)' \ + PATH='$(PWD)/_build/stage1/bin:$(PATH)' \ $(CABAL_BUILD) --ghc-options="-ghcversion-file=$(abspath ./rts/include/ghcversion.h)" -W $(GHC0) $(STAGE2_TARGETS) @echo "::endgroup::" @@ -632,8 +639,8 @@ $(addprefix _build/stage2/bin/,$(STAGE2_UTIL_EXECUTABLES)) &: $(CABAL) stage1 @echo "::group::Building stage2 utilities ($(STAGE2_UTIL_EXECUTABLES))..." # Force cabal to replan rm -rf _build/stage2/cache - HADRIAN_SETTINGS='$(HADRIAN_SETTINGS)' \ - PATH=$(PWD)/_build/stage1/bin:$(PATH) \ + GHC=$(GHC) HADRIAN_SETTINGS='$(HADRIAN_SETTINGS)' \ + PATH='$(PWD)/_build/stage1/bin:$(PATH)' \ $(CABAL_BUILD) --ghc-options="-ghcversion-file=$(abspath ./rts/include/ghcversion.h)" -W $(GHC0) $(STAGE2_UTIL_TARGETS) @echo "::endgroup::" @@ -705,7 +712,7 @@ _build/stage3/lib/targets/%/lib/ghc-interp.js: # $1 = TIPLET define build_cross - HADRIAN_SETTINGS='$(call HADRIAN_SETTINGS)' \ + GHC=$(GHC) HADRIAN_SETTINGS='$(call HADRIAN_SETTINGS)' \ PATH=$(PWD)/_build/stage2/bin:$(PWD)/_build/stage3/bin:$(PATH) \ $(CABAL_BUILD) -W $(GHC2) --happy-options="--template=$(abspath _build/stage2/src/happy-lib-2.1.5/data/)" --with-hsc2hs=$1-hsc2hs --hsc2hs-options='-x' --configure-option='--host=$1' \ $(foreach lib,$(CROSS_EXTRA_LIB_DIRS),--extra-lib-dirs=$(lib)) \ @@ -837,26 +844,26 @@ define patchpackageconf -e "s|data-dir:.*|data-dir: \"\$${pkgroot}/../lib/$4/$5$${sublib}\"|" \ -e "s|include-dirs:.*|include-dirs: \"\$${pkgroot}/../lib/$4/$5$${sublib}/include\"|" \ -e "s|^ /.*||" \ + -e "s|^ [A-Z]:.*||" \ $2 endef # $1 = triplet define copycrosslib @cp -rfp _build/stage3/lib/targets/$1 _build/bindist/lib/targets/ - @cd _build/bindist/lib/targets/$1/lib/package.conf.d ; \ + @ffi_incdir=`$(CURDIR)/_build/bindist/bin/$1-ghc-pkg field libffi-clib include-dirs | grep '/libffi-clib/src/' | sed 's|.*$(CURDIR)/||'` ; cd _build/bindist/lib/targets/$1/lib/package.conf.d ; \ for pkg in *.conf ; do \ pkgname=`echo $${pkg} | $(SED) 's/-[0-9.]*\(-[0-9a-zA-Z]*\)\?\.conf//'` ; \ pkgnamever=`echo $${pkg} | $(SED) 's/\.conf//'` ; \ mkdir -p $(CURDIR)/_build/bindist/lib/targets/$1/lib/$1/$${pkg%.conf} && \ cp -rfp $(CURDIR)/_build/stage3/$1/build/host/*/ghc-*/$${pkg%.conf}/build/* $(CURDIR)/_build/bindist/lib/targets/$1/lib/$1/$${pkg%.conf}/ && \ if [ $${pkgname} = "libffi-clib" ] ; then \ - ffi_incdir=`$(CURDIR)/_build/bindist/bin/$1-ghc-pkg field libffi-clib include-dirs | grep '/libffi-clib/src/' | sed 's|.*$(CURDIR)/||'` ; \ $(call patchpackageconf,$${pkgname},$${pkg},../../..,$1,$${pkgnamever}) ; \ - $(call copy_headers,ffitarget.h,$(CURDIR)/$${ffi_incdir},libffi-clib,$(CURDIR)/_build/bindist/bin/$1-ghc-pkg) ; \ else \ $(call patchpackageconf,$${pkgname},$${pkg},../../..,$1,$${pkgnamever}) ; \ fi ; \ - done + done ; \ + $(call copy_headers,ffitarget.h,$(CURDIR)/$${ffi_incdir},libffi-clib,$(CURDIR)/_build/bindist/bin/$1-ghc-pkg) endef # Target for creating the final binary distribution directory @@ -870,20 +877,20 @@ _build/bindist: stage2 driver/ghc-usage.txt driver/ghci-usage.txt # Copy libraries and settings from stage2 lib @cp -rfp _build/stage2/lib/{package.conf.d,settings,template-hsc.h} $@/lib/ @mkdir -p $@/lib/$(HOST_PLATFORM) - @cd $@/lib/package.conf.d ; \ - for pkg in *.conf ; do \ - pkgname=`echo $${pkg} | $(SED) 's/-[0-9.]*\(-[0-9a-zA-Z]*\)\?\.conf//'` ; \ - pkgnamever=`echo $${pkg} | $(SED) 's/\.conf//'` ; \ - mkdir -p $(CURDIR)/$@/lib/$(HOST_PLATFORM)/$${pkg%.conf} ; \ - cp -rfp $(CURDIR)/_build/stage2/build/host/*/ghc-*/$${pkg%.conf}/build/* $(CURDIR)/$@/lib/$(HOST_PLATFORM)/$${pkg%.conf} ; \ - if [ $${pkgname} = "libffi-clib" ] ; then \ - ffi_incdir=`$(CURDIR)/$@/bin/ghc-pkg field libffi-clib include-dirs | grep '/libffi-clib/src/' | sed 's|.*$(CURDIR)/||'` ; \ - $(call patchpackageconf,$${pkgname},$${pkg},../../..,$(HOST_PLATFORM),$${pkgnamever}) ; \ - $(call copy_headers,ffitarget.h,$(CURDIR)/$${ffi_incdir},libffi-clib,$(CURDIR)/$@/bin/ghc-pkg) ; \ - else \ - $(call patchpackageconf,$${pkgname},$${pkg},../../..,$(HOST_PLATFORM),$${pkgnamever}) ; \ - fi ; \ - done + @ffi_incdir=`$(CURDIR)/$@/bin/ghc-pkg field libffi-clib include-dirs | grep 'libffi-clib[/\\]src/' | sed 's/^[ \t]*//' | $(CYGPATH) | sed 's|.*$(CURDIR)/||'` ; \ + cd $@/lib/package.conf.d ; \ + for pkg in *.conf ; do \ + pkgname=`echo $${pkg} | $(SED) 's/-[0-9.]*\(-[0-9a-zA-Z]*\)\?\.conf//'` ; \ + pkgnamever=`echo $${pkg} | $(SED) 's/\.conf//'` ; \ + mkdir -p $(CURDIR)/$@/lib/$(HOST_PLATFORM)/$${pkg%.conf} ; \ + cp -rfp $(CURDIR)/_build/stage2/build/host/*/ghc-*/$${pkg%.conf}/build/* $(CURDIR)/$@/lib/$(HOST_PLATFORM)/$${pkg%.conf} ; \ + if [ $${pkgname} = "libffi-clib" ] ; then \ + $(call patchpackageconf,$${pkgname},$${pkg},../../..,$(HOST_PLATFORM),$${pkgnamever}) ; \ + else \ + $(call patchpackageconf,$${pkgname},$${pkg},../../..,$(HOST_PLATFORM),$${pkgnamever}) ; \ + fi ; \ + done ; \ + $(call copy_headers,ffitarget.h,$(CURDIR)/$${ffi_incdir},libffi-clib,$(CURDIR)/$@/bin/ghc-pkg) # Copy driver usage files @cp -rfp driver/ghc-usage.txt $@/lib/ @cp -rfp driver/ghci-usage.txt $@/lib/ diff --git a/cabal.project.stage2 b/cabal.project.stage2 index 6b49e7820a2c..53d6cb85043d 100644 --- a/cabal.project.stage2 +++ b/cabal.project.stage2 @@ -64,7 +64,7 @@ packages: utils/ghc-toolchain libraries/haskeline - libraries/terminfo +-- libraries/terminfo utils/hp2ps utils/hpc utils/ghc-iserv @@ -87,12 +87,15 @@ constraints: package * library-vanilla: True - library-for-ghci: True -- shared/executable-dynamic now controlled by Makefile (DYNAMIC variable) -- so we do not pin them here; default (static) remains when DYNAMIC=0. executable-profiling: False executable-static: False +if !os(windows) + package * + library-for-ghci: True + -- Maybe we should fix this with some import if os(linux) package rts @@ -142,6 +145,23 @@ if os(freebsd) ghc-options: "-optc-DFS_NAMESPACE=rts" flags: +tables-next-to-code +if os(windows) + package rts + ghc-options: "-optc-DProjectVersion=\"914\"" + ghc-options: "-optc-DHostPlatform=\"x86_64-unknown-mingw32\"" + ghc-options: "-optc-DHostArch=\"x86_64\"" + ghc-options: "-optc-DHostOS=\"windows\"" + ghc-options: "-optc-DHostVendor=\"unknown\"" + ghc-options: "-optc-DBuildPlatform=\"FIXME\"" + ghc-options: "-optc-DBuildArch=\"FIXME\"" + ghc-options: "-optc-DBuildOS=\"FIXME\"" + ghc-options: "-optc-DBuildVendor=\"FIXME\"" + ghc-options: "-optc-DGhcUnregisterised=\"FIXME\"" + ghc-options: "-optc-DTablesNextToCode=\"FIXME\"" + ghc-options: "-optc-DFS_NAMESPACE=rts" + flags: +tables-next-to-code + + program-options ghc-options: -fhide-source-paths -j diff --git a/cabal.project.stage3 b/cabal.project.stage3 index c4a0811278fa..4caa3cf27853 100644 --- a/cabal.project.stage3 +++ b/cabal.project.stage3 @@ -193,6 +193,21 @@ if os(freebsd) ghc-options: "-optc-DFS_NAMESPACE=rts" flags: +tables-next-to-code +if os(windows) + package rts + ghc-options: "-optc-DProjectVersion=\"914\"" + ghc-options: "-optc-DHostPlatform=\"x86_64-unknown-mingw32\"" + ghc-options: "-optc-DHostArch=\"x86_64\"" + ghc-options: "-optc-DHostOS=\"windows\"" + ghc-options: "-optc-DHostVendor=\"unknown\"" + ghc-options: "-optc-DBuildPlatform=\"FIXME\"" + ghc-options: "-optc-DBuildArch=\"FIXME\"" + ghc-options: "-optc-DBuildOS=\"FIXME\"" + ghc-options: "-optc-DBuildVendor=\"FIXME\"" + ghc-options: "-optc-DGhcUnregisterised=\"FIXME\"" + ghc-options: "-optc-DTablesNextToCode=\"FIXME\"" + ghc-options: "-optc-DFS_NAMESPACE=rts" + program-options ghc-options: -fhide-source-paths -j diff --git a/compiler/GHC/SysTools/BaseDir.hs b/compiler/GHC/SysTools/BaseDir.hs index 384169188e3e..bbbe0913e438 100644 --- a/compiler/GHC/SysTools/BaseDir.hs +++ b/compiler/GHC/SysTools/BaseDir.hs @@ -125,13 +125,7 @@ expandToolDir :: Bool -- ^ whether we use the ambient mingw toolchain -> Maybe FilePath -- ^ tooldir -> String -> String -#if defined(mingw32_HOST_OS) -expandToolDir False (Just tool_dir) s = expandPathVar "tooldir" tool_dir s -expandToolDir False Nothing _ = panic "Could not determine $tooldir" -expandToolDir True _ s = s -#else expandToolDir _ _ s = s -#endif -- | Returns a Unix-format path pointing to TopDir. findTopDir :: Maybe String -- Maybe TopDir path (without the '-B' prefix). @@ -169,21 +163,4 @@ findToolDir :: Bool -- ^ whether we use the ambient mingw toolchain -> FilePath -- ^ topdir -> IO (Maybe FilePath) -#if defined(mingw32_HOST_OS) -findToolDir False top_dir = go 0 (top_dir "..") [] - where maxDepth = 3 - go :: Int -> FilePath -> [FilePath] -> IO (Maybe FilePath) - go k path tried - | k == maxDepth = throwGhcExceptionIO $ - InstallationError $ "could not detect mingw toolchain in the following paths: " ++ show tried - | otherwise = do - let try = path "mingw" - let tried' = tried ++ [try] - oneLevel <- doesDirectoryExist try - if oneLevel - then return (Just path) - else go (k+1) (path "..") tried' -findToolDir True _ = return Nothing -#else findToolDir _ _ = return Nothing -#endif diff --git a/libraries/Cabal b/libraries/Cabal index 356ba348cf25..56ac96fbf855 160000 --- a/libraries/Cabal +++ b/libraries/Cabal @@ -1 +1 @@ -Subproject commit 356ba348cf25e930239190474287bf5ae6052738 +Subproject commit 56ac96fbf85589d2a243978b79a26d78782bd57b diff --git a/libraries/ghc-internal/configure.ac b/libraries/ghc-internal/configure.ac index 80f60072a421..8b47f2dd2600 100644 --- a/libraries/ghc-internal/configure.ac +++ b/libraries/ghc-internal/configure.ac @@ -11,9 +11,10 @@ CPPFLAGS="-I$srcdir $CPPFLAGS" AC_PROG_CC dnl make extensions visible to allow feature-tests to detect them later on AC_USE_SYSTEM_EXTENSIONS +AC_CANONICAL_HOST AC_MSG_CHECKING(for WINDOWS platform) -case $host_alias in +case $host in *mingw32*|*mingw64*|*cygwin*|*msys*|*windows*) WINDOWS=YES;; *) diff --git a/libraries/ghc-internal/src/GHC/Internal/IO/Windows/Paths.hs b/libraries/ghc-internal/src/GHC/Internal/IO/Windows/Paths.hs index 532cf1fc5ad7..98a500027805 100644 --- a/libraries/ghc-internal/src/GHC/Internal/IO/Windows/Paths.hs +++ b/libraries/ghc-internal/src/GHC/Internal/IO/Windows/Paths.hs @@ -28,7 +28,7 @@ import GHC.Internal.IO import GHC.Internal.Foreign.C.String import GHC.Internal.Foreign.Marshal.Alloc (free) -foreign import ccall safe "__hs_create_device_name" +foreign import ccall safe "__rts_create_device_name" c_GetDevicePath :: CWString -> IO CWString -- | This function converts Windows paths between namespaces. More specifically diff --git a/rts/RtsSymbols.c b/rts/RtsSymbols.c index 04df56636221..dde08d3e17ef 100644 --- a/rts/RtsSymbols.c +++ b/rts/RtsSymbols.c @@ -30,6 +30,7 @@ #include /* SHGetFolderPathW */ #include "IOManager.h" #include "win32/AsyncWinIO.h" +#include "fs.h" #endif #if defined(openbsd_HOST_OS) @@ -157,6 +158,8 @@ extern char **environ; * https://docs.microsoft.com/en-us/cpp/porting/visual-cpp-change-history-2003-2015?view=vs-2017#stdioh-and-conioh */ #define RTS_MINGW_ONLY_SYMBOLS \ + SymI_HasProto(__rts_swopen) \ + SymI_HasProto(__rts_create_device_name) \ SymI_HasProto(stg_asyncReadzh) \ SymI_HasProto(stg_asyncWritezh) \ SymI_HasProto(stg_asyncDoProczh) \ From afb4e5f022ae1922f8671e6a437f0718f4c27031 Mon Sep 17 00:00:00 2001 From: Julian Ospald Date: Fri, 21 Nov 2025 15:33:08 +0800 Subject: [PATCH 3/5] f --- .github/workflows/reusable-release.yml | 90 ++++++++++++++++++++++++++ Makefile | 6 +- cabal.project.stage2 | 5 +- cabal.project.stage3 | 1 + libraries/Cabal | 2 +- 5 files changed, 101 insertions(+), 3 deletions(-) diff --git a/.github/workflows/reusable-release.yml b/.github/workflows/reusable-release.yml index 165dfe27a831..c2d9f7dbb2bc 100644 --- a/.github/workflows/reusable-release.yml +++ b/.github/workflows/reusable-release.yml @@ -317,6 +317,53 @@ jobs: path: | ./_build/bindist/*.tar.gz + build-windows: + name: Build binary (Windows) + runs-on: windows-latest + env: + ADD_CABAL_ARGS: "" + ARTIFACT: "x86_64-mingw64" + ARCH: 64 + CABAL_DIR: "C:\\Users\\runneradmin\\AppData\\Roaming\\cabal" + strategy: + fail-fast: false + matrix: + branch: ${{ fromJSON(inputs.branches) }} + defaults: + run: + shell: msys2 {0} + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ matrix.branch }} + submodules: recursive + + - uses: msys2/setup-msys2@v2 + with: + msystem: CLANG64 + update: true + install: &msys2-install git vim winpty git tar bsdtar unzip binutils autoconf make xz curl libtool automake p7zip patch ca-certificates python3 zip mingw-w64-clang-x86_64-clang mingw-w64-clang-x86_64-python-sphinx mingw-w64-clang-x86_64-python-requests mingw-w64-clang-x86_64-tools-git tar gzip + path-type: inherit + + - name: Install GHCup + uses: haskell/ghcup-setup@v1 + with: + cabal: ${{ env.CABAL_VERSION }} + ghc: ${{ env.GHC_VERSION }} + + - name: Run build + run: *build + + - if: always() + name: Upload artifact + uses: ./.github/actions/upload + with: + if-no-files-found: error + retention-days: 2 + name: artifacts-${{ env.ARTIFACT }}-${{ matrix.branch }} + path: | + ./_build/bindist/*.tar.gz + build-freebsd-x86_64: name: Build FreeBSD x86_64 runs-on: [self-hosted, FreeBSD, X64] @@ -645,6 +692,49 @@ jobs: env: THREADS: 4 + test-windows: + name: Test binary (Windows) + runs-on: windows-latest + needs: ["build-windows"] + if: ${{ inputs.test }} + env: + ADD_CABAL_ARGS: "" + ARTIFACT: "x86_64-mingw64" + ARCH: 64 + CABAL_DIR: "C:\\Users\\runneradmin\\AppData\\Roaming\\cabal" + GHCUP_INSTALL_BASE_PREFIX: "/c" + strategy: + fail-fast: false + matrix: + branch: ${{ fromJSON(inputs.branches) }} + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ matrix.branch }} + submodules: recursive + + - uses: msys2/setup-msys2@v2 + with: + msystem: CLANG64 + update: true + install: *msys2-install + + - name: Install GHCup + uses: haskell/ghcup-setup@v1 + with: + cabal: ${{ env.CABAL_VERSION }} + ghc: ${{ env.GHC_VERSION }} + + - uses: ./.github/actions/download + with: + name: artifacts-${{ env.ARTIFACT }}-${{ matrix.branch }} + path: ./_build/bindist + + - name: Run test + run: *test + env: + THREADS: 4 + test-freebsd-x86_64: name: Test FreeBSD x86_64 runs-on: [self-hosted, FreeBSD, X64] diff --git a/Makefile b/Makefile index d485a39766e1..a94d988c98ad 100644 --- a/Makefile +++ b/Makefile @@ -109,7 +109,7 @@ CC := clang.exe CXX := clang++.exe CYGPATH = cygpath --unix -f - else -CYGPATH = echo +CYGPATH = cat endif EMCC ?= emcc @@ -261,6 +261,10 @@ STAGE2_UTIL_TARGETS := \ system-cxx-std-lib:system-cxx-std-lib \ xhtml:xhtml +ifneq ($(OS),Windows_NT) +STAGE2_UTIL_TARGETS += terminfo:terminfo +endif + # These things should be built on demand. # hp2ps:hp2ps \ # hpc-bin:hpc \ diff --git a/cabal.project.stage2 b/cabal.project.stage2 index 53d6cb85043d..fba7a9f85d42 100644 --- a/cabal.project.stage2 +++ b/cabal.project.stage2 @@ -64,13 +64,16 @@ packages: utils/ghc-toolchain libraries/haskeline --- libraries/terminfo utils/hp2ps utils/hpc utils/ghc-iserv utils/genapply utils/runghc +if !os(windows) + packages: + libraries/terminfo + -- project-rts -- project-ghc benchmarks: False diff --git a/cabal.project.stage3 b/cabal.project.stage3 index 4caa3cf27853..8c6ec1c7b3f4 100644 --- a/cabal.project.stage3 +++ b/cabal.project.stage3 @@ -207,6 +207,7 @@ if os(windows) ghc-options: "-optc-DGhcUnregisterised=\"FIXME\"" ghc-options: "-optc-DTablesNextToCode=\"FIXME\"" ghc-options: "-optc-DFS_NAMESPACE=rts" + flags: +tables-next-to-code program-options ghc-options: -fhide-source-paths -j diff --git a/libraries/Cabal b/libraries/Cabal index 56ac96fbf855..2309d2ca2d27 160000 --- a/libraries/Cabal +++ b/libraries/Cabal @@ -1 +1 @@ -Subproject commit 56ac96fbf85589d2a243978b79a26d78782bd57b +Subproject commit 2309d2ca2d276fe9fa2c971a8e4912602461c991 From a12f516223f77dad203c7132694cb4af9e158074 Mon Sep 17 00:00:00 2001 From: Julian Ospald Date: Fri, 21 Nov 2025 17:21:11 +0800 Subject: [PATCH 4/5] f --- .github/workflows/reusable-release.yml | 69 ++++++++++++++++++++------ 1 file changed, 53 insertions(+), 16 deletions(-) diff --git a/.github/workflows/reusable-release.yml b/.github/workflows/reusable-release.yml index c2d9f7dbb2bc..32f811904dee 100644 --- a/.github/workflows/reusable-release.yml +++ b/.github/workflows/reusable-release.yml @@ -33,6 +33,7 @@ env: TZ: Asia/Singapore EMSDK_VERSION: 3.1.74 MAKE_VERSION: 4.4 + MAKE: gmake jobs: tool-output: @@ -92,7 +93,8 @@ jobs: run: | ${{ matrix.platform.installCmd }} curl bash git ${{ matrix.platform.toolRequirements }} - - name: Install GHCup + - id: ghcup + name: Install GHCup uses: haskell/ghcup-setup@v1 with: cabal: ${{ env.CABAL_VERSION }} @@ -137,6 +139,14 @@ jobs: run: &build | set -eux + # On windows, we use msys2 shell, which does not by default inherit the windows PATHs. + # So although the ghcup action sets the PATH, it's not visible. We don't want to use + # 'pathtype: inherit', because it pollutes the msys2 paths, possibly leading to linking + # or other issues. So we just hardcode it here. + if [ ${{ runner.os }} = "Windows" ] ; then + export PATH="/c/ghcup/bin:$PATH" + fi + cabal update if [ -e "emsdk" ] ; then git config --system --add safe.directory $GITHUB_WORKSPACE @@ -144,9 +154,9 @@ jobs: cd emsdk source ./emsdk_env.sh cd .. - gmake CABAL=$PWD/_build/stage0/bin/cabal _build/bindist/haskell-toolchain.tar.gz _build/bindist/tests.tar.gz + ${{ env.MAKE }} CABAL=$PWD/_build/stage0/bin/cabal _build/bindist/haskell-toolchain.tar.gz _build/bindist/tests.tar.gz else - gmake CABAL=$PWD/_build/stage0/bin/cabal _build/bindist/ghc.tar.gz _build/bindist/cabal.tar.gz _build/bindist/tests.tar.gz + ${{ env.MAKE }} CABAL=$PWD/_build/stage0/bin/cabal _build/bindist/ghc.tar.gz _build/bindist/cabal.tar.gz _build/bindist/tests.tar.gz fi cd _build/bindist mv ghc.tar.gz ghc-$(bin/ghc --numeric-version)-${ARTIFACT}.tar.gz @@ -233,7 +243,8 @@ jobs: ref: ${{ matrix.branch }} submodules: recursive - - name: Install GHCup + - id: ghcup + name: Install GHCup uses: haskell/ghcup-setup@v1 with: cabal: ${{ env.CABAL_VERSION }} @@ -285,7 +296,8 @@ jobs: ref: ${{ matrix.branch }} submodules: recursive - - name: Install GHCup + - id: ghcup + name: Install GHCup uses: haskell/ghcup-setup@v1 with: cabal: ${{ env.CABAL_VERSION }} @@ -325,6 +337,8 @@ jobs: ARTIFACT: "x86_64-mingw64" ARCH: 64 CABAL_DIR: "C:\\Users\\runneradmin\\AppData\\Roaming\\cabal" + GHCUP_INSTALL_BASE_PREFIX: "C:\\" + GHCUP_MSYS2_ENV: CLANG64 strategy: fail-fast: false matrix: @@ -338,21 +352,26 @@ jobs: ref: ${{ matrix.branch }} submodules: recursive - - uses: msys2/setup-msys2@v2 + - id: msys2 + uses: msys2/setup-msys2@v2 with: msystem: CLANG64 update: true install: &msys2-install git vim winpty git tar bsdtar unzip binutils autoconf make xz curl libtool automake p7zip patch ca-certificates python3 zip mingw-w64-clang-x86_64-clang mingw-w64-clang-x86_64-python-sphinx mingw-w64-clang-x86_64-python-requests mingw-w64-clang-x86_64-tools-git tar gzip - path-type: inherit - - name: Install GHCup + - id: ghcup + name: Install GHCup uses: haskell/ghcup-setup@v1 with: cabal: ${{ env.CABAL_VERSION }} ghc: ${{ env.GHC_VERSION }} + env: + GHCUP_MSYS2: ${{ steps.msys2.outputs.msys2-location }} - name: Run build run: *build + env: + MAKE: "make" - if: always() name: Upload artifact @@ -384,7 +403,8 @@ jobs: ref: ${{ matrix.branch }} submodules: recursive - - name: Install GHCup + - id: ghcup + name: Install GHCup uses: haskell/ghcup-setup@v1 with: cabal: ${{ env.CABAL_VERSION }} @@ -553,7 +573,8 @@ jobs: - name: git clone fix run: git config --system --add safe.directory $GITHUB_WORKSPACE - - name: Install GHCup + - id: ghcup + name: Install GHCup uses: haskell/ghcup-setup@v1 with: cabal: ${{ env.CABAL_VERSION }} @@ -570,6 +591,14 @@ jobs: - name: Run test run: &test | + # On windows, we use msys2 shell, which does not by default inherit the windows PATHs. + # So although the ghcup action sets the PATH, it's not visible. We don't want to use + # 'pathtype: inherit', because it pollutes the msys2 paths, possibly leading to linking + # or other issues. So we just hardcode it here. + if [ ${{ runner.os }} = "Windows" ] ; then + export PATH="/c/ghcup/bin:$PATH" + fi + rm -rf .git cd _build/bindist for file in *.tar.gz; do tar xzf "$file"; done @@ -634,7 +663,8 @@ jobs: matrix: branch: ${{ fromJSON(inputs.branches) }} steps: - - name: Install GHCup + - id: ghcup + name: Install GHCup uses: haskell/ghcup-setup@v1 with: cabal: ${{ env.CABAL_VERSION }} @@ -671,7 +701,8 @@ jobs: matrix: branch: ${{ fromJSON(inputs.branches) }} steps: - - name: Install GHCup + - id: ghcup + name: Install GHCup uses: haskell/ghcup-setup@v1 with: cabal: ${{ env.CABAL_VERSION }} @@ -702,7 +733,8 @@ jobs: ARTIFACT: "x86_64-mingw64" ARCH: 64 CABAL_DIR: "C:\\Users\\runneradmin\\AppData\\Roaming\\cabal" - GHCUP_INSTALL_BASE_PREFIX: "/c" + GHCUP_INSTALL_BASE_PREFIX: "C:\\" + GHCUP_MSYS2_ENV: CLANG64 strategy: fail-fast: false matrix: @@ -713,17 +745,21 @@ jobs: ref: ${{ matrix.branch }} submodules: recursive - - uses: msys2/setup-msys2@v2 + - id: msys2 + uses: msys2/setup-msys2@v2 with: msystem: CLANG64 update: true install: *msys2-install - - name: Install GHCup + - id: ghcup + name: Install GHCup uses: haskell/ghcup-setup@v1 with: cabal: ${{ env.CABAL_VERSION }} ghc: ${{ env.GHC_VERSION }} + env: + GHCUP_MSYS2: ${{ steps.msys2.outputs.msys2-location }} - uses: ./.github/actions/download with: @@ -752,7 +788,8 @@ jobs: matrix: branch: ${{ fromJSON(inputs.branches) }} steps: - - name: Install GHCup + - id: ghcup + name: Install GHCup uses: haskell/ghcup-setup@v1 with: cabal: ${{ env.CABAL_VERSION }} From 538befd506bd4ea72117c196528e7694fa53a763 Mon Sep 17 00:00:00 2001 From: Julian Ospald Date: Fri, 21 Nov 2025 18:55:58 +0800 Subject: [PATCH 5/5] blah --- .github/workflows/reusable-release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/reusable-release.yml b/.github/workflows/reusable-release.yml index 32f811904dee..8750600193c4 100644 --- a/.github/workflows/reusable-release.yml +++ b/.github/workflows/reusable-release.yml @@ -357,7 +357,7 @@ jobs: with: msystem: CLANG64 update: true - install: &msys2-install git vim winpty git tar bsdtar unzip binutils autoconf make xz curl libtool automake p7zip patch ca-certificates python3 zip mingw-w64-clang-x86_64-clang mingw-w64-clang-x86_64-python-sphinx mingw-w64-clang-x86_64-python-requests mingw-w64-clang-x86_64-tools-git tar gzip + install: &msys2-install git vim winpty git tar bsdtar unzip binutils autoconf make xz curl libtool automake p7zip patch ca-certificates python3 zip mingw-w64-x86_64-gcc mingw-w64-x86_64-python-sphinx mingw-w64-x86_64-python-requests mingw-w64-x86_64-tools-git tar gzip - id: ghcup name: Install GHCup