Hide cbits symbols via visibility attribute or compiler flag?
- Dominant language
- Haskell
- Stars
- 1.7k
- Forks
- 750
- Avg merge
- 4d 3h
- Merged PRs (30d)
- 28
Description
**Describe the feature request**
When compiling `cbits`-style code (code that's designed for `foreign import` only by its containing library), it would be nice if there was some official/automatic way to restrict the [symbol visibility](https://gcc.gnu.org/wiki/Visibility) of the compiled bundled C code.
AIUI, there are a couple of ways to do this:
1. Set an attribute on the definitions. This is [`__attribute__((visibility))`](https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-visibility-function-attribute) on GCC >=4. I think Clang supports the same syntax and has done so for a long time. Still, it would be nice if we could signal (via `#define`?) that it's supported, so the code could still work with older compilers (assuming they're supported by GHC). GCC >=5 and at least Clang >=3.6 support the preprocessor symbol `__has_attribute(foo)`, but I don't know if MSVC does, or if GHC even supports MSVC.
2. Pass `-fvisibility=hidden` on the command line to set the default visibility and then change it where needed via `__attribute__`.
In my own C library projects, I only do "visibility stuff" if both №1 and №2 are available (i.e., most of the time on modern systems). When it's available, I set `-fvisibility=hidden` and then put (a macro that expands to) `__attribute__((visibility("default")))` on the public interface. For `cbits`-type stuff, there shouldn't _be_ a public interface, so we should just be able to hide everything that's `foreign import`ed, as it would only be referenced by the Haskell functions in the same Dynamic Shared Object (DSO).
Note that this isn't a _complete_ solution to the problem, as AIUI static libraries can't do visibility stuff. So you do still risk symbol clashes there (or the linker just picking one, maybe?).
**Additional context**
`crypton-0.30` [renamed some of its foreign imports](https://github.com/kazu-yamamoto/crypton/pull/10) to prevent a symbol clash during linking. This is exactly the "old woe" mentioned by the linked GCC wiki page.
I saw someone on irc://irc.libera.chat/reflex-frp just yesterday having problems with `cryptonite` (I have advised him to switch to `crypton`) and `libsodium` using the same symbols:
7:04 AM Oh no! I almost had my iOS build, but in the very last build step - frontend-static-aarch64-ios-0.1 - I get 'ld: 6 duplicate symbols for architecture arm64'
7:07 AM Via different dependencies, I have two cryptography libraries, 'cryptonite' for Haskell and 'libsodium' for C. Linking them together statically clashes.
7:14 AM All 6 duplicates stem from 'blake2b-ref.o'
9:04 AM I don't think we use blake anywhere in our app. Going to local-fork either cryptonite or libsodium and rip blake2-ref out. Or does anyone here know like, a linker option to make them coexist?
9:04 AM or so?
Contributor guide
Research direction
The issue names no files or tests; start by tracing Cabal's cbits compilation path and how foreign imports are linked. Compare GCC and Clang visibility support with the static-library limitation described here, and define done as an agreed, portable mechanism for restricting bundled C symbols.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- c, haskell
- Domain
- build-system
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 35/100