Skip to content

[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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

hyp
Copy link
Contributor

@hyp hyp commented Apr 4, 2024

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.

@hyp
Copy link
Contributor Author

hyp commented Apr 4, 2024

@swift-ci please test

@hyp hyp force-pushed the eng/custom-cxx-stdlib branch from 84c0643 to 8ed9e8b Compare April 4, 2024 20:31
@hyp hyp marked this pull request as ready for review April 4, 2024 20:31
@hyp
Copy link
Contributor Author

hyp commented Apr 4, 2024

@swift-ci please test

@hyp hyp force-pushed the eng/custom-cxx-stdlib branch from 8ed9e8b to 8cdbaa6 Compare April 5, 2024 00:12
@hyp
Copy link
Contributor Author

hyp commented Apr 5, 2024

@swift-ci please test

@fahadnayyar fahadnayyar self-requested a review April 8, 2024 16:42
@hyp
Copy link
Contributor Author

hyp commented Apr 9, 2024

@swift-ci please test

@hyp hyp requested review from hjyamauchi and compnerd April 9, 2024 18:15
@hyp
Copy link
Contributor Author

hyp commented Apr 9, 2024

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">,
Copy link
Member

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.

Copy link
Contributor

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

Copy link
Contributor Author

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.

@hyp
Copy link
Contributor Author

hyp commented Apr 11, 2024

@swift-ci please test linux platform

@hyp
Copy link
Contributor Author

hyp commented Apr 11, 2024

@swift-ci please test windows

@hyp
Copy link
Contributor Author

hyp commented Apr 11, 2024

@swift-ci please test linux

@hyp
Copy link
Contributor Author

hyp commented Apr 12, 2024

@swift-ci please smoke test

@hyp
Copy link
Contributor Author

hyp commented Apr 16, 2024

The sample project that demonstrates the use case:
https://github.com/hyp/swift-cxx-custom-libcxx-sample

@hyp hyp force-pushed the eng/custom-cxx-stdlib branch from a3fab96 to b750f7e Compare April 16, 2024 18:37
@hyp hyp force-pushed the eng/custom-cxx-stdlib branch from b750f7e to 69be6f9 Compare April 16, 2024 18:47
@hyp
Copy link
Contributor Author

hyp commented Apr 16, 2024

@swift-ci please test

@egorzhdan egorzhdan added the c++ interop Feature: Interoperability with C++ label Apr 24, 2024
@tbkka tbkka requested review from MaxDesiatov and al45tair May 10, 2024 16:59
@etcwilde
Copy link
Member

Mulling this over still. Do we need to specify the path to the C++ stdlib, or should that be found in the --sysroot that @compnerd is working on, and then we have something like -cxx-stdlib, that's effectively like -stdlib on clang++ today and searches in there for the appropriate modulemaps and libraries? I'm a tad worried about the growing number of different places we can get mismatched libraries from, when it seems like that's the purpose of a sysroot.

@compnerd
Copy link
Member

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

@etcwilde
Copy link
Member

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.

@egorzhdan
Copy link
Contributor

macOS had both libstdc++ and libc++ while transitioning from GNU tools to LLVM. Which one was the "default"?

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.

What if I make a Linux distro with libc++ as my C++ 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.

@egorzhdan
Copy link
Contributor

@hyp are you still interested in landing this patch? Do you folks still need this functionality on your side?

@compnerd
Copy link
Member

compnerd commented Jul 9, 2024

@egorzhdan yes, we're still in need of this functionality, but currently a little over subscribed with other work :(

@egorzhdan
Copy link
Contributor

Parts of this PR were superseded by #75589.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c++ interop Feature: Interoperability with C++
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants