我有一段看起来像这样的简单 C++ 代码:
#include <boost/timer/timer.hpp>
int main(void) {
boost::timer::auto_cpu_timer t;
return 0;
}
我尝试编译并链接它(使用 gcc 4.8.1 和 GNU ld 2.23.52.20130828)如下:
$ g++ -o test test.cc -lboost_timer
/usr/bin/ld: /tmp/cc2jP1jv.o: undefined reference to symbol '_ZN5boost6system15system_categoryEv'
/usr/lib/libboost_system.so.1.54.0: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status
-lboost_system
一种解决方案是在命令行上明确提及,这很有效。但是,我也可以这样做:
$ g++ -Wl,--copy-dt-needed-entries -o test test.cc -lboost_timer
根据 ld 文档“将递归搜索命令行中提到的 --copy-dt-needed-entries 动态库,按照它们的 DT_NEEDED 标记到其他库,以解析输出二进制文件所需的符号”,所以这个一切都说得通: ld 从 boost_timer 弄清楚它还需要链接到 boost_system 以解析所有符号。
但是,我意识到这也有效:
$ g++ -fPIC -shared -o test test.cc -lboost_timer
显然,我现在生成了一个共享对象而不是一个可执行文件。不过,显然 ld 能够确定它需要将共享对象与 boost_system 链接起来:
$ ldd test | grep boost_system
libboost_system.so.1.54.0 => /usr/lib/libboost_system.so.1.54.0 (0x00007f385246e000)
所以我的问题是:为什么在构建共享对象和可执行文件时符号解析不同?ld 如何在没有我指定的情况下确定我的共享对象应该与 boost_system 链接--copy-dt-needed-entries
?