Skip to content

Add -dynamic when linking shared haskell_binary#1345

Open
jbellerb wants to merge 1 commit into
facebook:mainfrom
jbellerb:main
Open

Add -dynamic when linking shared haskell_binary#1345
jbellerb wants to merge 1 commit into
facebook:mainfrom
jbellerb:main

Conversation

@jbellerb

Copy link
Copy Markdown

This matches the behavior of Cabal when linking binaries. Without this flag, will GHC statically link every implicit dependency provided by the global package database. I've noticed a few strange behaviors caused by this, all involving haskell_prebuilt_library:

  • examples/with_prelude/haskell segfaults on macOS. The binary contains both statically and dynamically linked copies of rts, but only the static copy is initialized. The dynamic copy comes via //haskell:library (haskell_library passes -dynamic). Linux symbol namespacing would merge the two, but macOS doesn't.

  • if the global package database is limited to only rts (GHC is hard-coded to require this), linking fails on Linux using lld. Linking the static rts against a dynamic base would require creating copy relocations for read-only symbols in base.

  • if the global package database is limited as above, any resulting binary would throw a runtime linker error on macOS. On macOS, GHC sets -dead_strip_dylibs to remove unused dylibs. During static linking, symbols required by base are removed and the rts dylib is stripped as dead code.

I can't find a reason for why the flag was originally excluded. Based on the issues it causes, including it seems like the correct behavior.

This matches the behavior of Cabal when linking binaries. Without this
flag, will GHC statically link every implicit dependency provided by the
global package database. I've noticed a few strange behaviors caused by
this, all involving `haskell_prebuilt_library`:

- `examples/with_prelude/haskell` segfaults on macOS. The binary
  contains both statically and dynamically linked copies of `rts`, but
  only the static copy is initialized. The dynamic copy comes via
  `//haskell:library` (`haskell_library` passes `-dynamic`). Linux
  symbol namespacing would merge the two, but macOS doesn't.

- if the global package database is limited to only `rts` (GHC is
  hard-coded to require this), linking fails on Linux using lld. Linking
  the static `rts` against a dynamic `base` would require creating copy
  relocations for read-only symbols in `base`.

- if the global package database is limited as above, any resulting
  binary would throw a runtime linker error on macOS. On macOS, GHC sets
  `-dead_strip_dylibs` to remove unused dylibs. During static linking,
  symbols required by `base` are removed and the `rts` dylib is stripped
  as dead code.

I can't find a reason for why the flag was originally excluded. Based on
the issues it causes, including it seems like the correct behavior.
@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Jun 15, 2026
@meta-codesync

meta-codesync Bot commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

This pull request has been imported. If you are a Meta employee, you can view this in D108573242. (Because this pull request was imported automatically, there will not be any future comments.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant