Fix "undefined reference to `fmt::v7::detail::basic_data<void>::digits'" - #2333
Conversation
|
I wonder why it doesn't happen in CI. Could you provide repro details? |
|
Pseudocmake: Because If link |
|
Adding the combination to the test suite would certainly help catch problems in the future. |
|
I believe, you are also linking to fmtlib incorrectly because the error occurs not in Note that libfmt is not linked transitively to add_library(mylibrary SHARED lib.cpp)
target_link_libraries(mylibrary PRIVATE libfmt.a) # link with static fmtwhile you seem to be using libfmt in your add_executable(exe main.cpp)
target_link_libraries(exe PRIVATE mylibrary) # Error: undefined reference to `fmt::v7::detail::basic_data<void>::digits'I think, a clear (non-pseudo) example is necessary to understand the scenario. |
|
@sergiud, No. The exe target does not use fmt functions anywhere and cannot depend on it. |
|
I cannot reproduce the problem at ad97258. Here's my MWE:
cmake_minimum_required (VERSION 3.0)
project (fmt-link)
set (CMAKE_CXX_VISIBILITY_PRESET hidden)
find_package (fmt REQUIRED)
add_library (mylib SHARED mylib.cpp)
target_link_libraries (mylib PRIVATE fmt::fmt)
add_executable (myexe myexe.cpp)
target_link_libraries (myexe PRIVATE mylib)
#include <fmt/format.h>
__attribute__((visibility("default")))
std::string foo()
{
return fmt::format("foo bar {}", 42);
}
#include <string>
#include <iostream>
extern std::string foo();
int main()
{
std::cout << foo() << std::endl;
} |
|
Build: Error: |
|
openSUSE Leap 15.2 |
|
Still no linker error. I copy pasted your modifications and used a local clone of fmtlib included via I'm on ArchLinux with gcc version 11.1.0. Edit: I missed the |
|
The culprit seems to be the combination diff --git a/include/fmt/format.h b/include/fmt/format.h
index 3f6ab357..71df6ced 100644
--- a/include/fmt/format.h
+++ b/include/fmt/format.h
@@ -902,7 +902,7 @@ template <typename T = void> struct basic_data {
FMT_API static constexpr const char right_padding_shifts[] = {0, 31, 0, 1, 0};
};
-#ifndef FMT_HEADER_ONLY
+#if !defined(FMT_HEADER_ONLY) && defined(FMT_EXPORT)
// Required for -flto, -fivisibility=hidden and -shared to work
extern template struct basic_data<void>;
#endif@phprus Can you verify this? |
|
I will check this change a little later today. But anyway static libraries don't need visibility attribute. Therefore, I think it would be better to change the FMT_API as well. |
|
In this case condition |
| # define FMT_CLASS_API | ||
| # if defined(__GNUC__) || defined(__clang__) | ||
| # define FMT_API __attribute__((visibility("default"))) | ||
| # define FMT_EXTERN_TEMPLATE_API FMT_API |
There was a problem hiding this comment.
Why did you remove FMT_EXTERN_TEMPLATE_API definition?
There was a problem hiding this comment.
FMT_EXTERN_TEMPLATE_API was added in the partial incorrect commit 13e6529 and is not used anywhere.
There was a problem hiding this comment.
Right, "partial incorrect commit" 👎
FMT_EXTERN_TEMPLATE_API was used before. But you're correct to note that it is not necessary anymore.
|
Could you also please add the combination to the test suite? This case is currently not being tested. |
5729075 to
ac89e52
Compare
|
Test added. |
|
Great, thanks! LGTM |
|
Don't merge now. |
|
Note that you can transform this PR to Draft until you are ready. |
|
Changes applied. |
Remove unused FMT_EXTERN_TEMPLATE_API
|
Merged, thank you both! |
If static fmt library is used in shared library.
Error in commit 13e6529.