-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
clang 17 vs clang 18+ and gcc 13 binaries linking problem #102443
Comments
My guess is that the templates don't get instantiated, possibly because they are not referenced? At least not in the expected object file? I would be good if you could reduce this quite a bit, since the whole of Abseil is way too much. :) |
@DimitryAndric I don't know, it worked as expected with clang-17 and the only difference is used compiler, so something triggered change in behavior in newer clang versions I was able to build/link all three projects with clang-18 by requesting explicit instantiation in one of common files in my projects:
|
unfortunately despite explicitly specifying "18+" in problem description I was actually unable to test it against clang 19 and 20 as both barks at boost.future but I suppose that's another story: |
|
We are having the same abseil linking problem when trying to upgrade from LLVM 17 to 18. I created a reproduction Bazel workspace at https://github.com/mering/llvm-18-linking-issue. See the When changing the |
This gives me a 404, probably the access rights not public? |
Oops sorry, now it should be public. |
I played a little with my reproduction example and noticed that it builds correctly with any of the following changes:
|
I could reduce the abseil dependency to 3 headers and 1 source file (all with minimal content): https://github.com/mering/llvm-18-linking-issue/tree/main/abseil-cpp/absl. I verified that it fails to link with 18.1.4 but links just fine with 17.0.6. Interestingly, when I use |
When I try the bazelisk commands exactly as you specified in that repository, I get an error right away:
If I try to use the plain
I have roughly zero knowledge of how bazel or bazelisk work, so I can only conclude that it does not work as advertised. :) |
I think it would be much easier if you could just reduce this to a series of compile commands, followed by a link command. I.e. a list of Usually this can be scraped from a build tool's log output, when you run it in verbose mode (since hiding what those tools are actually doing is unfortunately the norm these days). |
You are missing the The following command should work for you:
|
If you run with |
Right, that seems to go further, but the downloaded llvm binaries bomb out because they try to use
I'll have to spin up a container with some old Ubuntu version in there. Probably 22.04 will do? |
Yes, |
The linker parameters are (also containing the paths to interesting files):
The namespace absl {
namespace log_internal {
template LogMessage& LogMessage::operator<<(const int& v);
} // namespace log_internal
} // namespace absl |
For LLVM 17.0.6, it contains the following symbols:
For LLVM 18.1.4, it contains the following symbols:
With LLVM 18 the symbol seems to contain the |
I ditched the whole bazel thing and just used clang++-18 (from apt.llvm.org) directly:
The only thing I had to modify to get it to compile that way is adding a diff --git a/test/test.cc b/test/test.cc
index 6303a1a..62bfc2d 100644
--- a/test/test.cc
+++ b/test/test.cc
@@ -1,3 +1,4 @@
+#include <cstdint>
// SOURCE: https://github.com/google/googletest/blob/v1.14.0/googletest/include/gtest/gtest-message.h#L121-L150
#include <type_traits>
// NOTE The linker error disappears when using "absl/strings/has_absl_stringify.h" instead of "absl/strings/internal/has_absl_stringify.h". I.e. the error is not dependent on whether you are using this sandbox environment, or just the native host toolchain. |
Now that I got it in a simpler for to compile, I could bisect, and it looks like this particular use case is broken (or fixed ;) ) after I am pretty much unsure if this is a wanted or unwanted side-effect of this change. |
@DimitryAndric Thanks for bisecting! I can confirm that it builds successfully when using |
@DimitryAndric @mering That works for me as well! Thank you :-) |
It would still be nice if one of the experts could explain what the correct way is to declare these templates, so they can be emitted and found by the linker? :) |
clang changed their mangling rules since clang-18, and some symbols in absl_log have different symbol names between clang-17/ndk-25 and clang-18/ndk-26 Related: llvm/llvm-project#102443
clang changed their mangling rules since clang-18, and some symbols in absl_log have different symbol names between clang-17/ndk-26 and clang-18/ndk-27 Related: llvm/llvm-project#102443
clang changed their mangling rules since clang-18, and some symbols in absl_log have different symbol names between clang-17/ndk-26 and clang-18/ndk-27 Related: llvm/llvm-project#102443
clang changed their mangling rules since clang-18, and some symbols in absl_log have different symbol names between clang-17/ndk-26 and clang-18/ndk-27 Related: llvm/llvm-project#102443
The Abseil code isn't incorrect. Between Clang 17 and Clang 18, we implemented an ABI fix to resolve mangled name collisions, but unfortunately that changes the manglings of a small number of functions such as this one (which previously was a case where mangling collisions between different functions could happen). The ABI change fixed a longstanding bug, but we finally reached sufficient motivation to fix it due to some C++20 changes, primarily the addition of concepts, which made these kinds of symbol collisions more likely to occur in practice in the future. This was just an all-round bad situation, and sadly we didn't have a path forward that supported C++20 well and had no risk of breaking anything. There are a few paths forward for code affected by this:
On the Clang side, we could investigate emitting the symbol with both the old and the new mangling (eg, when we see a reference to a function template specialization that we can't instantiate locally due to an extern template declaration, and its mangling changed due to this ABI change, we could emit a definition of the symbol as a weak alias to the old mangled name). GCC has the ability to do this to mitigate the pain of mangling changes. But I'm worried that this would break more than it fixes... Another possibility we could consider would be to add support for a |
This is due to llvm/llvm-project#102443. PiperOrigin-RevId: 712978370
This is due to ubuntu-latest was updated to 24.04 with Clang/LLVM 18, which is known to have issues with Abseil: llvm/llvm-project#102443 PiperOrigin-RevId: 712978370
This is due to ubuntu-latest was updated to 24.04 with Clang/LLVM 18, which is known to have issues with Abseil: llvm/llvm-project#102443 PiperOrigin-RevId: 712978370
This is due to ubuntu-latest was updated to 24.04 with Clang/LLVM 18, which is known to have issues with Abseil: llvm/llvm-project#102443 PiperOrigin-RevId: 712978370
This is due to ubuntu-latest was updated to 24.04 with Clang/LLVM 18, which is known to have issues with Abseil: llvm/llvm-project#102443 PiperOrigin-RevId: 713103399
The change is contagious and painful to maintain, to say at least. What is happening right now is:
Attempt to fix with A task in gcc was created: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114383 to fix case 1. But if they ever do it, gcc-future would start to produce libraries that can't be linked to gcc-current. Will they allow that? |
Could you please try 19 or |
By |
after upgrading ubuntu 23.10 to 24.04 and clang from 17 to 18 cannot build my grpc related projects with clang 18 (and newer) due to link time undefined symbol in debug config:
grpc (and abseil) were installed using vcpkg and gcc 13 and I've had no problems building my projects with either clang 17 or gcc 13, but not so with clang 18+
I can see differences in generated symbols between clang 17 and 18, there's missing "U absl::lts_20240116::log_internal::LogMessage& absl::lts_20240116::log_internal::LogMessage::operator<< <unsigned long, 0>(unsigned long const&)"
~/.vs/LCS/out/build/linux-debug-clang-18/bin/reference/CMakeFiles/lcsref.dir$ nm grpc.cpp.o -C | grep LogMessage::operator 0000000000000000 W absl::lts_20240116::log_internal::LogMessage::operator<<(unsigned long) 0000000000000000 W absl::lts_20240116::log_internal::LogMessage& absl::lts_20240116::log_internal::LogMessage::operator<< <19>(char const (&) [19])
vs
~/.vs/LCS/out/build/linux-debug-clang-17/bin/reference/CMakeFiles/lcsref.dir$ nm grpc.cpp.o -C | grep LogMessage::operator 0000000000000000 W absl::lts_20240116::log_internal::LogMessage::operator<<(unsigned long) 0000000000000000 W absl::lts_20240116::log_internal::LogMessage& absl::lts_20240116::log_internal::LogMessage::operator<< <19>(char const (&) [19]) U absl::lts_20240116::log_internal::LogMessage& absl::lts_20240116::log_internal::LogMessage::operator<< <unsigned long, 0>(unsigned long const&)
corresponding abseil lib indeed has those templated operator << versions (including <unsigned long, 0>) declared in abseil log_message.h as
/opt/vcpkg/installed/x64-linux/lib$ nm libabsl_log_internal_message.a -C | grep LogMessage::operator 0000000000000da0 T absl::lts_20240116::log_internal::LogMessage::operator<<(std::ostream& (*)(std::ostream&)) 00000000000000fa t absl::lts_20240116::log_internal::LogMessage::operator<<(std::ostream& (*)(std::ostream&)) [clone .cold] 0000000000000e20 T absl::lts_20240116::log_internal::LogMessage::operator<<(std::ios_base& (*)(std::ios_base&)) 0000000000000120 t absl::lts_20240116::log_internal::LogMessage::operator<<(std::ios_base& (*)(std::ios_base&)) [clone .cold] 00000000000011b0 T absl::lts_20240116::log_internal::LogMessage::operator<<(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) 0000000000001380 T absl::lts_20240116::log_internal::LogMessage::operator<<(std::basic_string_view<char, std::char_traits<char> >) 0000000000000000 W absl::lts_20240116::log_internal::LogMessage& absl::lts_20240116::log_internal::LogMessage::operator<< <signed char, 0>(signed char const&) 0000000000000000 W absl::lts_20240116::log_internal::LogMessage& absl::lts_20240116::log_internal::LogMessage::operator<< <bool, 0>(bool const&) 0000000000000000 W absl::lts_20240116::log_internal::LogMessage& absl::lts_20240116::log_internal::LogMessage::operator<< <char, 0>(char const&) 0000000000000000 W absl::lts_20240116::log_internal::LogMessage& absl::lts_20240116::log_internal::LogMessage::operator<< <double, 0>(double const&) 0000000000000000 W absl::lts_20240116::log_internal::LogMessage& absl::lts_20240116::log_internal::LogMessage::operator<< <float, 0>(float const&) 0000000000000000 W absl::lts_20240116::log_internal::LogMessage& absl::lts_20240116::log_internal::LogMessage::operator<< <unsigned char, 0>(unsigned char const&) 0000000000000000 W absl::lts_20240116::log_internal::LogMessage& absl::lts_20240116::log_internal::LogMessage::operator<< <int, 0>(int const&) 0000000000000000 W absl::lts_20240116::log_internal::LogMessage& absl::lts_20240116::log_internal::LogMessage::operator<< <unsigned int, 0>(unsigned int const&) 0000000000000000 W absl::lts_20240116::log_internal::LogMessage& absl::lts_20240116::log_internal::LogMessage::operator<< <long, 0>(long const&) 0000000000000000 W absl::lts_20240116::log_internal::LogMessage& absl::lts_20240116::log_internal::LogMessage::operator<< <unsigned long, 0>(unsigned long const&) 0000000000000000 W absl::lts_20240116::log_internal::LogMessage& absl::lts_20240116::log_internal::LogMessage::operator<< <void const*, 0>(void const* const&) 0000000000000000 W absl::lts_20240116::log_internal::LogMessage& absl::lts_20240116::log_internal::LogMessage::operator<< <void*, 0>(void* const&) 0000000000000000 W absl::lts_20240116::log_internal::LogMessage& absl::lts_20240116::log_internal::LogMessage::operator<< <short, 0>(short const&) 0000000000000000 W absl::lts_20240116::log_internal::LogMessage& absl::lts_20240116::log_internal::LogMessage::operator<< <unsigned short, 0>(unsigned short const&) 0000000000000000 W absl::lts_20240116::log_internal::LogMessage& absl::lts_20240116::log_internal::LogMessage::operator<< <long long, 0>(long long const&) 0000000000000000 W absl::lts_20240116::log_internal::LogMessage& absl::lts_20240116::log_internal::LogMessage::operator<< <unsigned long long, 0>(unsigned long long const&)
so atm I'm unable to build my projects with clang-18+
The text was updated successfully, but these errors were encountered: