[cfe-dev] May libc++ support symbol versioning?
David Chisnall via cfe-dev
cfe-dev at lists.llvm.org
Wed Feb 26 09:16:33 PST 2020
On 26/02/2020 16:28, Zhihao Yuan wrote:
>> I would be interested to know who is making that statement on behalf of
>> the FreeBSD project. We made a conscious decision not to use symbol
>> versioning for the FreeBSD build of libc++ when we imported it.
> The thread is here; you are welcome to check it out:
>
> https://lists.freebsd.org/pipermail/freebsd-hackers/2020-February/055669.html
FWIW: Joerg is exactly correct in that thread. Symbol versioning does
not solve the problem, for precisely the reasons that he outlines. C++
inline namespaces provide a strictly richer set of functionality than
ELF symbol versioning and libc++ uses them for ABI stability. This does
not help libraries that pass libc++ types across library boundaries.
For example, consider library A defines a function:
void printString(std::string);
Library B calls this function.
Library A is compiled with the current version of libc++. This function
is mangled as:
_Z11printStringNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE
Which translates to:
printString(std::__1::basic_string<char, std::__1::char_traits<char>,
std::__1::allocator<char> >)
Now we release a new version of libc++ which provides a new ABI-breaking
std::string representation and use the __2 inline namespace. Both can
coexist in the same libc++ binary.
Library A moves to a new version of libc++ and recompiles against the
new headers. Now the same function becomes the mangled equivalent of:
printString(std::__2::basic_string<char, std::__1::char_traits<char>,
std::__2::allocator<char> >)
(Assuming that char_traits and allocator remain the same). Now library
B will get link failures.
Now, it would be possible for library A to explicitly provide a compat
version of the printString function by providing a function like this:
void printString(std::__2::string);
In C++, if both provide an adequate API, it would even be possible to
move the implementation into a template that is instantiated in two
overloads of printString, one with std::__1::string and the other with
std::string.
Unfortunately, that's the trivial case. Any classes declared in headers
exposed by library A will also need compat versions.
Given that most libraries will not go to this trouble, the end result is
effectively a flag day. That is not so bad for FreeBSD, where the
entire package set is built together. It would be possible to ship a
version of libc++ that included both the __1 and __2 symbols but
defaulted to the __2 versions, then rebuild the ports collection (which
happens at least once a week anyway) against the __2 version once all of
the older versions of the base system have reached EOL.
David
More information about the cfe-dev
mailing list