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

Reply via email to