ldionne wrote: > I'm still not sure this is a good idea, if there ever was a > XcodeDefault.xctoolchain/usr/lib/libc++.dylib it wouldn't be linkable from > anything outside of Xcode (its `LC_ID_DYLIB` would either be an absolute path > that would break if someone had their Xcode in a different location, or it > would be `@rpath` based which would break for anyone not contributing to > Xcode). Why can't we solve this with an extra linker search path in the > bootstrapping case?
This whole change basically has nothing to do with Xcode or the way we distribute libc++ on Apple platforms as a system library. It's all about unbreaking the toolchain we produce in *upstream* builds of Clang and libc++. On Apple platforms, libc++ may be shipped in two different ways: 1. As a system library, with the headers and `.tbd` part of the SDK, and with the `.dylib` as part of the shared cache. When that's the case, Clang (whether AppleClang or LLVM Clang) will pick up libc++ from the `-isysroot`. This is the way we (at Apple) build and ship libc++. 2. Then, there's how everyone else is using libc++ based on upstream LLVM Clang: as part of the toolchain. In that world, we build Clang and libc++ within a single bootstrapping build, and libc++ is installed at `<toolchain>/usr/include/c++/v1` and `<toolchain>/usr/lib`. When you invoke Clang, you still provide a SDK because you need various headers to do anything useful (e.g. the `libc` headers and any other Apple system headers you might want to use). But that SDK already contains a different copy of `libc++` under `<SDK>/usr/include/c++/v1` and `<SDK>/usr/lib` (which has an arbitrary other version and has been configured differently -- think of it as being an entirely different library which happens to have the same name). Hence, Clang needs to do something in order to pick up the libc++ that you *actually* want to use, which is the one you built as part of your bootstrap and are shipping with your toolchain. That's why the Clang driver looks at whether `<toolchain>/usr/include/c++/v1` exists, and if so, [it uses that path](https://github.com/llvm/llvm-project/blob/ed6078c02368e0f2cf4025f1f03f27f00b4d6b5c/clang/lib/Driver/ToolChains/Darwin.cpp#L2753) instead of `<SDK>/usr/include/c++/v1` for the C++ stdlib headers. Unfortunately, it doesn't do the same thing for the `dylib`, which leads to it mixing `<toolchain>/usr/include/c++/v1` with `<SDK>/usr/lib`. Not only does that make no sense, this actually breaks in all kinds of way since, as I said, they're two different libraries. So for example the headers will advertise that some function exists in the dylib, but the dylib actually doesn't contain that function. At the moment, this fundamentally breaks any attempt to build and use upstream libc++ on Darwin as part of a toolchain -- which is pretty much as bad as it gets. This has resulted in numerous issues like the comments in https://github.com/llvm/llvm-project/issues/77653 and Homebrew being broken: https://github.com/Homebrew/homebrew-core/issues/235411. So, why is that more of a problem now than it was in the past? Simply because we've introduced more differences between the `libc++.dylib` we ship in the SDK and the upstream one (e.g. typed memory allocation). We've also added new symbols to the built library upstream, which means that the headers now think that `libc++.dylib` should provide those symbols. But if you link against the wrong `libc++.dylib`, well obviously they're not present. So, again, this has nothing to do with the way we ship libc++ within Xcode. In the Xcode case, there is no libc++ in the toolchain, so we always fall back to the SDK (for headers and for linking). https://github.com/llvm/llvm-project/pull/170303 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
