将共享对象链接到其他共享对象 C++ 项目

Posted

技术标签:

【中文标题】将共享对象链接到其他共享对象 C++ 项目【英文标题】:Linking a shared object into other shared object C++ project 【发布时间】:2015-09-30 15:56:37 【问题描述】:

我在一个非常大的 C++ 项目中工作,以创建一个大的共享对象,我们正在使用一个外部 SDK,该 SDK 有几个头文件和几个属于彼此的共享库。这意味着 SDK 类的声明在头文件中,但它们的定义在共享对象中。

我知道由于头文件中的声明,我可以编译此代码。

但我不明白的是我什么时候必须明确指定链接器使用的共享对象?

也就是说,如果我指定它(例如在 cmake 中使用 target_link_libraries 命令),那么链接器可以检查一个符号是否在共享库中。但是如果我不指定它会发生什么(即链接中没有任何 -l[shared_object_name] 标志)?我的经验是(这让我感到惊讶)工作正常(即整个构建过程完成)。怎么可能?

【问题讨论】:

一些编译器,例如 Microsoft-VC 有一个#pragma,允许您在源代码中指定编译器和链接器选项。 Boost 使用它来根据编译器宏自动选择正确的共享库。 我们在linux下使用GCC,不使用#pragma :( 【参考方案1】:

在 POSIX 共享库中,您可以在共享库中包含未定义的符号,并且所有符号都可以正常链接。只要可执行文件完全链接,就不会出现链接器错误。

这样做是因为动态库模仿静态库的行为,而静态库可以有未定义的符号(静态库一开始没有链接)。

如果您来自 Windows 背景,那么您会感到惊讶,因为 Windows DLL 不能有未定义的符号。

如果您对此感到担心,可以检查链接器选项--no-undefined--no-allow-shlib-undefined

【讨论】:

这意味着在可执行文件中它必须链接我的共享对象和我的共享对象中使用的共享对象?相反,我的共享对象找不到所用符号的主体。 @TiborTakács:是的。您的共享对象没有尝试在其他共享对象中查找符号。当您构建一个实际的可执行文件时,这一切都会得到解决。 @TiborTakács: 如果第一个 SO 链接到第二个 SO,它会在第一个 SO 头中添加一个 NEEDED 条目,这样当 exe 链接到第一个 SO 时,第二个 SO 将自动链接进去。但是,如果您链​​接第一个 SO 而没有第二个 SO,则 exe 将需要链接到两者,否则它将失败。【参考方案2】:

我的经验是(这让我很惊讶)工作正常(即整个构建过程完成)。

这似乎不太可能。

事实上……

这怎么可能?

不是。

唯一的解释是您没有使用这些库文件中定义的符号。它们要么位于第三方代码的仅标头部分,要么根本不是第三方代码的一部分。

或者您正在构建自己的共享库。不过,最终的可执行文件仍然需要链接的第三方库。

【讨论】:

我也在创建一个共享库。这是一个原因吗? @TiborTakács:是的。这是一个关键的细节,从一开始就应该存在于问题中。就目前而言,我的答案的原始最后一段就是你要找的。​​span>

以上是关于将共享对象链接到其他共享对象 C++ 项目的主要内容,如果未能解决你的问题,请参考以下文章

使用共享对象 (libtensorflow_cc.so) 的 C++ 编译项目失败

在共享对象链接期间指定整个存档包含

如何在pybind11中将共享指针列表传递给c++对象

异常安全 C++ 共享指针

静态链接 libtcod

linux C++。链接共享对象和主