I have a trivial piece of C++ code that looks something like this:
#include <boost/timer/timer.hpp>
int main(void) {
boost::timer::auto_cpu_timer t;
return 0;
}
I tried to compile and link it (with gcc 4.8.1 and GNU ld 2.23.52.20130828) as follows:
$ 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
One solution is to explicitly mention -lboost_system
on the command line, and that works. However, I can also do:
$ g++ -Wl,--copy-dt-needed-entries -o test test.cc -lboost_timer
According to the ld documentation "with --copy-dt-needed-entries dynamic libraries mentioned on the command line will be recursively searched, following their DT_NEEDED tags to other libraries, in order to resolve symbols required by the output binary", so this all makes sense: ld is figuring out from boost_timer that it also needs to link against boost_system in order to resolve all the symbols.
However, I realised that this also works:
$ g++ -fPIC -shared -o test test.cc -lboost_timer
Obviously, I've now generated a shared object rather than an executable. Apparently, though, ld was able to figure out that it needed to link the shared object against boost_system:
$ ldd test | grep boost_system
libboost_system.so.1.54.0 => /usr/lib/libboost_system.so.1.54.0 (0x00007f385246e000)
So my question is this: why is symbol resolution different when building a shared object versus an executable? How is ld able to figure out that my shared object should be linked against boost_system without my specifying --copy-dt-needed-entries
?