Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SR-1021] Don't export public symbols from static libraries by default #43633

Open
jckarter opened this issue Mar 22, 2016 · 9 comments
Open
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior.

Comments

@jckarter
Copy link
Member

Previous ID SR-1021
Radar None
Original Reporter @jckarter
Type Bug
Additional Detail from JIRA
Votes 3
Component/s
Labels Bug
Assignee None
Priority Medium

md5: 8df16971f82bdca1788af1569c947c46

relates to:

  • SR-521 Public symbols are never dead stripped

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.

@belkadan
Copy link
Contributor

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).

@gottesmm
Copy link
Member

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.

@keith
Copy link
Collaborator

keith commented Feb 13, 2022

To get the more-dylib-like static lib, some folks use `ld -r` with `-exported_symbols_list` to strip out the non-public symbols.

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
@isaac-weisberg
Copy link

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...

@jckarter
Copy link
Member Author

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.

@compnerd
Copy link
Collaborator

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.

@jckarter
Copy link
Member Author

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).

@compnerd
Copy link
Collaborator

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.

@jckarter
Copy link
Member Author

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior.
Projects
None yet
Development

No branches or pull requests

6 participants