@@ -132,6 +132,10 @@ module GHC.Driver.Session (
132132 sGhcWithInterpreter ,
133133 sLibFFI ,
134134 sTargetRTSLinkerOnlySupportsSharedLibs ,
135+ sTargetIsDynamic ,
136+ sTargetShipsDynLibs ,
137+ sTargetIsProfiled ,
138+ sTargetShipsProfLibs ,
135139 GhcNameVersion (.. ),
136140 FileSettings (.. ),
137141 PlatformMisc (.. ),
@@ -3548,8 +3552,16 @@ compilerInfo dflags
35483552 (" Have native code generator" , showBool $ platformNcgSupported platform),
35493553 (" target has RTS linker" , showBool $ platformHasRTSLinker platform),
35503554 (" Target default backend" , show $ platformDefaultBackend platform),
3551- -- Whether or not we support @-dynamic-too@
3552- (" Support dynamic-too" , showBool $ not isWindows),
3555+ -- Whether or not we support @-dynamic-too@ for this target.
3556+ -- Historically `not isWindows` (Windows tooling couldn't do
3557+ -- it). Now also gated on the per-target `sTargetIsDynamic`
3558+ -- dial — if the target isn't dynamic-capable, -dynamic-too
3559+ -- is meaningless. Keep the Windows guard as defence in depth
3560+ -- for pre-this-patch bindists on Windows that lack the key
3561+ -- and so default sTargetIsDynamic=True (the AND would
3562+ -- otherwise regress them).
3563+ (" Support dynamic-too" , showBool $ not isWindows
3564+ && sTargetIsDynamic (settings dflags)),
35533565 -- Whether or not we support the @-j@ flag with @--make@.
35543566 (" Support parallel --make" , " YES" ),
35553567 -- Whether or not we support "Foo from foo-0.1-XXX:Foo" syntax in
@@ -3569,10 +3581,27 @@ compilerInfo dflags
35693581 (" Uses package keys" , " YES" ),
35703582 -- Whether or not we support the @-this-unit-id@ flag
35713583 (" Uses unit IDs" , " YES" ),
3572- -- Whether or not GHC was compiled using -dynamic
3573- (" GHC Dynamic" , showBool hostIsDynamic),
3574- -- Whether or not GHC was compiled using -prof
3575- (" GHC Profiled" , showBool hostIsProfiled),
3584+ -- Reported as YES iff *both* per-target settings dials say so:
3585+ -- `target is dynamic` — the GHC for this target
3586+ -- can produce dynamic output
3587+ -- `target ships dynamic libraries` — the lib tree actually has
3588+ -- .dyn_hi / .so artifacts
3589+ -- cabal-install reads this to decide whether to enable
3590+ -- @library-dynamic@ by default. The target's per-target settings
3591+ -- file completely controls this value — no host-RTS dependency,
3592+ -- so on a multi-target bindist with one shared stage2 GHC binary
3593+ -- different targets can correctly disagree. Both keys default to
3594+ -- True if absent (matches pre-this-change behaviour).
3595+ (" GHC Dynamic" , showBool (sTargetIsDynamic (settings dflags)
3596+ && sTargetShipsDynLibs (settings dflags))),
3597+ -- Profiling-way analogue of `GHC Dynamic`. Per-target dials
3598+ -- via `target is profiled` + `target ships profiling libraries`
3599+ -- settings keys. Drops the historical `hostIsProfiled` RTS-
3600+ -- baked-in for the same reason the dyn pair did: on a multi-
3601+ -- target bindist the shared stage2 GHC binary's prof-ness is
3602+ -- fixed but the lib trees can disagree per target.
3603+ (" GHC Profiled" , showBool (sTargetIsProfiled (settings dflags)
3604+ && sTargetShipsProfLibs (settings dflags))),
35763605 (" Debug on" , showBool debugIsOn),
35773606 (" LibDir" , topDir dflags),
35783607 -- This is always an absolute path, unlike "Relative Global Package DB" which is
@@ -3782,18 +3811,26 @@ makeDynFlagsConsistent dflags
37823811 = let warn = " -dynamic is ignored when using -staticlib"
37833812 in loop dflags{targetWays_ = removeWay WayDyn (targetWays_ dflags)} warn
37843813 -- For the wasm target, when ghc is invoked with -dynamic,
3785- -- when linking the final .wasm binary we must still ensure
3786- -- the static archives are selected. Otherwise wasm-ld would
3787- -- fail to find and link the .so library dependencies. wasm-ld
3788- -- can link PIC objects into static .wasm binaries fine, so we
3789- -- only adjust the ways in the final linking step, and only
3790- -- when linking .wasm binary (which is supposed to be fully
3791- -- static), not when linking .so shared libraries.
3792- | LinkExecutable _ <- ghcLink dflags
3793- , ArchWasm32 <- arch
3794- , ways dflags `hasWay` WayDyn
3795- = let warn = " -dynamic is ignored when linking binaries on WASM"
3796- in loop dflags{targetWays_ = removeWay WayDyn (targetWays_ dflags)} warn
3814+ -- (DISABLED Phase 6.5, 2026-05-26) — the original rule below was meant
3815+ -- to strip WayDyn only when linking the final .wasm binary, but the
3816+ -- default `ghcLink` in `defaultDynFlags` is `LinkExecutable Dynamic`, so
3817+ -- the rule fired for EVERY --make invocation that didn't override it.
3818+ -- That broke cabal library builds with `shared:True, library-vanilla:False`
3819+ -- (the rule stripped WayDyn mid-compile, then GHC looked for vanilla .hi
3820+ -- files that don't exist since only .dyn_hi was produced).
3821+ --
3822+ -- The wasm linker (wasm-ld) silently handles -dynamic without issue —
3823+ -- wasm binaries are inherently single-file artifacts, and PIC objects
3824+ -- link fine into them. Removing the strip lets WayDyn flow through to
3825+ -- the actual link step, where wasm-ld does the right thing.
3826+ -- (If a future regression surfaces, narrow the rule to fire ONLY in the
3827+ -- actual link phase, not at flag-consistency time.)
3828+ --
3829+ -- | LinkExecutable _ <- ghcLink dflags
3830+ -- , ArchWasm32 <- arch
3831+ -- , ways dflags `hasWay` WayDyn
3832+ -- = let warn = "-dynamic is ignored when linking binaries on WASM"
3833+ -- in loop dflags{targetWays_ = removeWay WayDyn (targetWays_ dflags)} warn
37973834
37983835 | LinkInMemory <- ghcLink dflags
37993836 , not (gopt Opt_ExternalInterpreter dflags)
0 commit comments