-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[cxx-interop] Support compiling using a custom C++ stdlib #72843
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
base: main
Are you sure you want to change the base?
Conversation
b810900
to
84c0643
Compare
@swift-ci please test |
84c0643
to
8ed9e8b
Compare
@swift-ci please test |
8ed9e8b
to
8cdbaa6
Compare
@swift-ci please test |
@swift-ci please test |
Still fixing up some of the tests, but it's ready for the first round of review. |
@@ -939,6 +939,11 @@ def cxx_interop_disable_requirement_at_import : | |||
HelpText<"Do not require C++ interoperability to be enabled when importing a Swift module that enables C++ interoperability">, | |||
Flags<[FrontendOption, HelpHidden]>; | |||
|
|||
def cxx_interop_libcxx_path: JoinedOrSeparate<["-"], "clang-libcxx-path">, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this spelt with a -clang
prefix? I think that we shouldn't use libcxx
because this is confusing as people struggle to differentiate:
- libcxx
- libc++
- libstdc++
- stl_port
- msvcprt
Can we make this generic like -cxx-stl-path
? I think that using -stdlib=
to match clang might be confusing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed that we shouldn't call this libcxx
, however, Clang doesn't use stl
in the user-facing command like flags, so I wouldn't use it for Swift either. I would probably call this -clang-cxx-stdlib=
or -clang-stdlib=
or -cxx-stdlib=
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Renaming to -cxx-stdlib-path
.
@swift-ci please test linux platform |
@swift-ci please test windows |
@swift-ci please test linux |
@swift-ci please smoke test |
The sample project that demonstrates the use case: |
a3fab96
to
b750f7e
Compare
b750f7e
to
69be6f9
Compare
@swift-ci please test |
Mulling this over still. Do we need to specify the path to the C++ stdlib, or should that be found in the |
@etcwilde unfortunately, I think that it is reasonable to be able to replace the C++ runtime for a platform. It is allowed by the specification (though generally speaking, one is only permitted to have 1 C++ runtime in the address space). |
absolutely, no disagreement there. I don't think this change covers as many cases as it should, and I don't want to end up with a dozen similar but subtly different flags for specifying which C++ runtime you want and where to look for it. macOS had both libstdc++ and libc++ while transitioning from GNU tools to LLVM. Which one was the "default"? What if I make a Linux distro with libc++ as my C++ runtime? Why is libstdc++ still the "default" there? It shouldn't be. What if I want to use the libstdc++ from the redhat devtoolset so I can use newer C++ features on older distros? Whether the library is libstdc++ or libc++ and where it lives are independent of eachother. That last case is particularly interesting because I could have one module built against the libstdc++ in the devtoolset and another against a libc++ from elsewhere, and those would both be "sealed", but still end up with multiple C++ runtimes. At the very least, I think we need to encode which c++ runtime a module is built against. |
I think Swift should assume that the default C++ stdlib is the one picked by Clang by default. I think trying to make Swift smarter than Clang in terms of choosing the stdlib/runtime is dangerous, because most people (myself included) would assume that if they don't specify the stdlib/runtime manually, building a C++ library and linking a Swift executable against it should "just work", i.e. pick the same default C++ stdlib/runtime.
The Swift toolchain for that distro would then get built with libc++, and that would be the default C++ stdlib from Swift's point of view on that distro. This seems correct to me. |
@hyp are you still interested in landing this patch? Do you folks still need this functionality on your side? |
@egorzhdan yes, we're still in need of this functionality, but currently a little over subscribed with other work :( |
Parts of this PR were superseded by #75589. |
This PR adds a new frontend flag
-clang-libcxx-path
, that lets you specify a path to a custom C++ standard library that should be used when importing C++ modules into Swift. This flag instructs clang importer to ignore system's default stdlib, and instead use the given path for C++ stdlib headers. This also means that it prevents the use of CxxStdlib overlay with the custom stdlib. It also adds a new define__swift_use_custom_libcxx__
to the clang importer in this mode, to allow C++ headers to enforce that they're being imported with a custom stdlib into Swift.A swift module that builds with
-clang-libcxx-path
also provides a mechanism that allows users to effectively seal the module's use of C++ APIs, to prevent leakage of the custom C++ stdlib dependency to other Swift modules. This is done both by prohibiting the import of other modules that use C++ interoperability without a custom stdlib, and also by prohibiting the use of C++ types in public Swift APIs. Additionally, clients can use@_implementationOnly
imports to further seal the custom C++ stdlib dependency across a non-resilient module boundary, and Swift will validate that the deserialized Swift type layout doesn't leak its custom C++ module dependencies into other Swift modules.