Skip to content

Commit 7c565de

Browse files
committed
fix: export RTS symbols for GHC API programs in dynamic builds
Programs that link against the ghc package and use features like Template Haskell or GHCi need to export RTS symbols to dynamically loaded libraries. When these programs load Haskell shared libraries via dlopen(), those libraries reference RTS symbols like stg_INTLIKE_closure. Without exporting these symbols from the executable, dlopen fails with "undefined symbol". This fix adds platform-specific linker flags to GHC's static linker when building executables that depend on the ghc package in dynamic mode: - Linux/FreeBSD: -rdynamic (passes --export-dynamic to ld) - macOS: -flat_namespace (makes all symbols visible across namespaces) - Windows: not needed (--enable-auto-import already handles this) This complements the similar fix for ghc-iserv (f8ca34d) and fixes testsuite failures for tests like T5313, T8639_api, and dynCompileExpr that use the GHC API with interpreterBackend. See Note [Export dynamic symbols for GHC API programs] in GHC/Linker/Static.hs and Note [ghc-iserv and dynamic symbol export] in utils/ghc-iserv/ghc-iserv.cabal.in for full details.
1 parent f8ca34d commit 7c565de

File tree

1 file changed

+28
-0
lines changed

1 file changed

+28
-0
lines changed

compiler/GHC/Linker/Static.hs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,24 @@ it is supported by both gcc and clang. Anecdotally nvcc supports
6868
-Xlinker, but not -Wl.
6969
-}
7070

71+
{-
72+
Note [Export dynamic symbols for GHC API programs]
73+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
74+
Programs linking against the ghc package need to export symbols from
75+
the RTS to dynamically loaded libraries. When running GHCi or Template
76+
Haskell, these programs load Haskell shared libraries via dlopen() that
77+
reference RTS symbols like stg_INTLIKE_closure. Without exporting these
78+
symbols from the executable, dlopen will fail with "undefined symbol".
79+
80+
Platform-specific solutions:
81+
Linux/FreeBSD: -rdynamic (passes --export-dynamic to ld)
82+
macOS: -flat_namespace (makes all symbols visible across namespaces)
83+
Windows: not needed (--enable-auto-import handles this)
84+
85+
This is the same issue that ghc-iserv faces, and is documented in
86+
utils/ghc-iserv/ghc-iserv.cabal.in as Note [ghc-iserv and dynamic symbol export].
87+
-}
88+
7189
linkBinary :: Logger -> TmpFs -> DynFlags -> ExecutableLinkMode -> UnitEnv -> [FilePath] -> [UnitId] -> IO ()
7290
linkBinary = linkBinary' False
7391

@@ -252,6 +270,16 @@ linkBinary' staticLink logger tmpfs dflags blm unit_env o_files dep_units = do
252270
then ["-Wl,--gc-sections"]
253271
else [])
254272

273+
-- See Note [Export dynamic symbols for GHC API programs]
274+
++ (if ways_ `hasWay` WayDyn &&
275+
any ((== "ghc") . unitPackageNameString) pkgs
276+
then case platformOS platform of
277+
os | osElfTarget os -> ["-rdynamic"]
278+
OSDarwin -> ["-Wl,-flat_namespace"]
279+
-- OSMinGW32 already has --export-all-symbols via --enable-auto-import
280+
_ -> []
281+
else [])
282+
255283
++ o_files
256284
++ lib_path_opts)
257285
++ extra_ld_inputs

0 commit comments

Comments
 (0)