Open jckarter opened 8 years ago
The original reason to export symbols was because the statically-linked executable could provide a runtime for any dynamic frameworks it depended on. That turns out to not really work (and we never even really tried to get it close-to-working).
For a long time I have wanted a static library that was less like an archive and more like a finished product ala a dylib.
For instance, you could internalize the symbols in the "static" dylib.
To get the more-dylib-like static lib, some folks use `ld -r` with `-exported_symbols_list` to strip out the non-public symbols.
This is so relatable... I really wish there was a simple way to hide all public symbols in the resulting product from every single dependency this product depends on...
On the bright side, I believe we now know during compilation whether we're building for a static library or not (because @compnerd needed this info to deal with Windows' linkage model). Maybe we could use that information here too to switch over to hidden linkage for public
symbols when we know we're building for an executable or static library target.
Yes, that should be possible. This is effectively what happens with Windows - public
symbols in a static library are marked as internal
for the loader. Note that this might cause some headache - people may be improperly expecting that the static library symbol to be available to external consumers as the import may not be marked as @_implementationOnly
.
Well, it would be great to ban that too, since reexporting a static library dependency from a dynamic library is rarely a good idea (unless the static library itself was built to be part of the eventual dynamic library, in which case we could still build it as if for a dynamic library to begin with).
I agree with the basic premise of that. I think that if the library is built statically to be exposed by an eventual dynamic library, we do need a way to clearly express that intent. At least on Windows, this will require some amount of arrangement - the functions should be marked as __declspec(dllexport)
but then used without __declspec(dllimport)
which we do not currently support as we cannot identify that the library is meant to be exposed when built statically. If there are ideas on how to express that intent, I would be rather interested in them.
Yeah, it probably requires more coordination with the build system to be able to tell the compiler what modules/packages are destined to be part of the same image or not.
Additional Detail from JIRA
| | | |------------------|-----------------| |Votes | 3 | |Component/s | | |Labels | Bug | |Assignee | None | |Priority | Medium | md5: 8df16971f82bdca1788af1569c947c46relates to:
Issue Description:
When we statically link Swift libraries into executables, the public symbols from those libraries should not be exported from the result executable. This can be done at link time by passing
--exclude-libs
to GNU ld (I couldn't find an equivalent flag for ld64 at a glance), or we could do it at compile time by only emitting symbols with hidden visibility when we know we're building for a static library.When we link static libraries into a dynamic library, it's a more interesting policy decision whether those libraries' symbols should be exported by the dynamic library. IMO we shouldn't by default, unless the dynamic library module explicitly reexports APIs from its static dependencies as its own public API. This would definitely require compiler support, though.