c++ - Protobuf ld undefined symbol ~InternalMetadata()

标签 c++ linker embedded protocol-buffers

我在我的库中遇到了一些相当基本的 Protobuf 文件的问题。这是成功构建为静态库的,但是当编译测试(Catch2)并链接到相同的 protobuf 库时,我得到以下 undefined symbol :-

[build] Starting build
[proc] Executing command: /usr/local/bin/cmake --build /Volumes/TB3-1/git/skunkworks/herald-for-cpp/build --config Debug --target herald-tests --
[build] [1/1 100% :: 0.182] Linking CXX executable herald-tests/herald-tests
[build] FAILED: herald-tests/herald-tests 
[build] : && /usr/bin/clang++ -g -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.3.sdk -Wl,-search_paths_first -Wl,-headerpad_max_install_names  herald-tests/CMakeFiles/herald-tests.dir/test-templates.cpp.o herald-tests/CMakeFiles/herald-tests.dir/test-util.cpp.o herald-tests/CMakeFiles/herald-tests.dir/mesh-tests.cpp.o herald-tests/CMakeFiles/herald-tests.dir/main.cpp.o -o herald-tests/herald-tests  herald/libherald.a  /usr/local/lib/libprotobuf.a  /usr/local/opt/openssl@3/lib/libcrypto.a && :
[build] Undefined symbols for architecture x86_64:
[build]   "google::protobuf::internal::InternalMetadata::~InternalMetadata()", referenced from:
[build]       google::protobuf::MessageLite::~MessageLite() in libherald.a(modem.pb.cc.o)
[build]       google::protobuf::MessageLite::~MessageLite() in libherald.a(mesh.pb.cc.o)
[build]       google::protobuf::MessageLite::~MessageLite() in libherald.a(models.pb.cc.o)
[build] ld: symbol(s) not found for architecture x86_64
[build] clang: error: linker command failed with exit code 1 (use -v to see invocation)
[build] ninja: build stopped: subcommand failed.
[build] Build finished with exit code 1

super 有趣的是,当我强制使用 SPEED 而不是 LITE_RUNTIME 时,它甚至会提示 ~MessageLite 调用中缺少符号。无论我将库和程序链接到 dylib 还是我的 mac 上的静态库,无论是完整库还是精简库,似乎都不重要。在我的原型(prototype)文件中尝试了 SPEED 和 LITE_RUNTIME,结果完全相同。

我已经为此苦苦挣扎了一段时间。任何想法都非常感激。

注意:我的库的目标平台范围从服务器上的容器到嵌入式硬件设备。这些特定的测试是在本地编译的(目前在我的例子中是 Mac OS X x86_64 Intel Mac)。

最佳答案

本期was tracked here并且应该在最近发布的 Protobuf 3.21.3 中修复。

随包管理器一起提供的库构建通常使用 NDEBUG 构建。定义( -DNDEBUG 到编译器, #define NDEBUG 在代码中)。通常这只是关闭检查 assert()宏,但 Protobuf 按下此符号可以打开和关闭其自身的内部调试。事实证明,在 Release模式下 InternalMetadata析构函数始终是内联的,并且(在编译器选项中使用 -fvisibility-inlines-hidden)从未生成要链接的符号,而在 Debug模式下,它并不总是内联的,需要链接。

因此尝试构建未定义 NDEBUG 的用户代码Protobuf header 将导致需要链接到该析构函数的代码,而该析构函数不会包含在发布的 Protobuf 打包库中。

解决方法是使用 -DNDEBUG在您的应用程序中,或者构建 Protobuf 的调试版本来链接,或者使用足够新的 Protobuf(3.21.3+)或足够旧的 Protobuf(我认为 <=3.19)不会出现此特定问题。

唯一剩下的谜团是,为什么整个互联网在过去几天都注意到了这个错误,而它已经存在了很长时间。

关于c++ - Protobuf ld undefined symbol ~InternalMetadata(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73047153/

相关文章:

c - 如何合并两个二进制可执行文件?

c++ - 递归函数中在堆上分配与在堆栈上分配

c++ - MFC PrintWindow(CPaintDC) 工作但 PrintWindow(CDC) 不工作

ios - Apple Mach-O 链接器与第三方 SDK 发生错误

C++ 将 2d 数组(由 uniqe_ptr 引用)合并到 3d 数组中

c++ - 静态链接可以导致执行一些初始化例程吗?

python - 将 Python 移植到嵌入式系统

audio - 麦克风的低频分量过大

c++ - Kruskal算法和不相交集数据结构: Do I need the following two lines of code?

c++ - 将字符串连接到 char*