Apple's libc++ now provides std::__type_descriptor_t functionality not found in upstream libc++?

Maybe somebody here can help me out: On macOS, I build my own local Clang and libc++ trunk versions, and have used them successfully (to in turn build LibreOffice with them) in the past. I use DYLD_LIBRARY_PATH to make the generated executables find my local libc++.1.dylib. Which apparently always used to be a backwards-compatible superset of the system’s libc++.1.dylib, so things happened to work. (Even when running an executable like my local clang—which I had built against the system toolchain, so it is expecting to be run against the system’s libc++.1.dylib—against a DYLD_LIBRARY_PATH pointing at my local libc++.1.dylib.)

But now when I updated to macOS 14 and Xcode 15, the system’s libc++.1.dylib apparently contains symbols like __ZnamSt19__type_descriptor_t (i.e., operator new[](unsigned long, std::__type_descriptor_t)) that are not provided by recent LLVM 18 trunk libc++ (and git grep type_descriptor_t across all the llvm-project repo turns up no sign of it). So e.g. running my locally built clang --version against a DYLD_LIBRARY_PATH pointing at my local libc++.1.dylib now fails with

dyld[19204]: weak-def symbol not found '__ZnwmSt19__type_descriptor_t'weak-def symbol not found '__ZnamSt19__type_descriptor_t'
Abort trap: 6
2 Likes

Same issue here

1 Like

There is something I don’t understand, the fact that the system library has additional symbols shouldn’t be a problem. I guess you are running a program that expects to be run against the system dylib, against the just-built trunk dylib and then your program is failing to find some of the symbols it wants.

Generally speaking, you shouldn’t assume that trunk libc++ is compatible with the Apple system libc++ — we are free to add/remove symbols from it and you should consider it to be a different stdlib (eg like GNU libstdc++) for all intents and purposes. So the issue here is that you swapped the system dylib for an incompatible one but I don’t understand your setup in enough details to try to suggest a solution at this point.

On 10/10/23 01:10, Louis Dionne via LLVM Discussion Forums wrote:

There is something I don’t understand, the fact that the system library
has additional symbols shouldn’t be a problem. I guess you are running a
program that expects to be run against the system dylib, against the
just-built trunk dylib and then your program is failing to find some of
the symbols it wants.

Exactly. (As I wrote: “[…] things happened to work. (Even when
running an executable like my local clang—which I had built against
the system toolchain, so it is expecting to be run against the system’s
libc++.1.dylib—against a DYLD_LIBRARY_PATH pointing at my local
libc++.1.dylib.)”

Generally speaking, you shouldn’t assume that trunk libc++ is compatible
with the Apple system libc++ — we are free to add/remove symbols from it
and you should consider it to be a different stdlib (eg like GNU
libstdc++) for all intents and purposes. So the issue here is that you
swapped the system dylib for an incompatible one but I don’t understand
your setup in enough details to try to suggest a solution at this point.
Yeah, that this setup happened to work reasonably well for so long
apparently set false expectations on my side :slight_smile:

Anyway, I now noticed that at least the trunk LLVM 18 toolchain that I’m
using is generating executables that reference (the LLVM 18 version of
libc++.1.dylib via) @rpath/libc++.1.dylib, but fails to also add an
LC_RPATH to those generated executables. So what I’m now doing to build
LibreOffice against a trunk LLVM 18 toolchain, incl. a trunk LLVM 18
libc++.1.dylib, is to not set DYLD_LIBRARY_PATH at all and rather add an
appropriate -Wl,-rpath,… to my LDFLAGS. And things work fine again
for me. :slight_smile:

Check your DYLD_LIBRARY_PATH and check the order in which the paths are declared.

Unlike your path env that many declare like this:

export PATH=“/llvm/bin:$PATH”

You want to concat any amendments to the array at the end, not the beginning. So if you have any DYLD_LIBRARY_PATH’s declared, do so like this instead:

export DYLD_LIBRARY_PATH=“$DYLD_LIBRARY_PATH:$NEWPATH/lib”

This way, the system linker’s take precedent in cases where it may be necessary. Also, it doesn’t have to do with clang itself, I believe there is a clang-tool that installs a dyld with the same name as a system dyld. And for some reason it causes issues.

This is late but I guess it can be helpful to anyone else having the same issue.

1 Like