Почему GNU ld по-разному разрешает символы при связывании исполняемых файлов с общими объектами?

У меня есть тривиальный фрагмент кода 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?


person user2862505    schedule 09.10.2013    source источник
comment
Вы пробовали с -shared -z defs ?   -  person CB Bailey    schedule 09.10.2013
comment
@CharlesBailey Добавление -z defs в общую сборку приводит к ее поломке (test.cc:(.text+0x85): undefined reference to 'boost::system::generic_category()'). Глядя на -z defs, я также указал на --[no-]allow-shlib-undefined, и это может объяснить, что происходит... спасибо за подсказку!   -  person user2862505    schedule 09.10.2013


Ответы (2)


Я думаю, что прямой ответ на мой вопрос находится в опции --[no-]allow-shlib-undefined для ld. Со страницы руководства:

Поведение по умолчанию — сообщать об ошибках для любых неопределенных символов, на которые есть ссылки в общих библиотеках, если компоновщик используется для создания исполняемого файла, но разрешать их, если компоновщик используется для создания общей библиотеки.

Поэтому, когда я строю с -shared, символы в boost_system не определены, но поведение ld по умолчанию не заботится. Можно сказать заботиться:

$ g++ -fPIC -shared -Wl,--no-allow-shlib-undefined -o test test.cc -lboost_timer
/usr/bin/ld: /tmp/cc6j1de3.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

Точно так же мы можем сказать ему не заботиться о сборке исполняемого файла:

$ g++ -Wl,--allow-shlib-undefined -o test test.cc -lboost_timer
/tmp/ccUHoCIU.o: In function `__static_initialization_and_destruction_0(int, int)':
test.cc:(.text+0x7a): undefined reference to `boost::system::generic_category()'
test.cc:(.text+0x86): undefined reference to `boost::system::generic_category()'
test.cc:(.text+0x92): undefined reference to `boost::system::system_category()'
collect2: error: ld returned 1 exit status

Но создание двоичного файла не удается без возможности определить эти символы.

Спасибо @CharlesBailey за то, что указал мне правильное направление!

person user2862505    schedule 09.10.2013

В команде collect2 есть различия, которые могут иметь значение. Различные команды сравниваются на http://imgur.com/eMr2tY2. Правая часть создает разделяемую библиотеку (-fPic -shared), левая — обычную компиляцию.

person user2862931    schedule 09.10.2013
comment
это может быть вопрос не по теме. Но ваше изображение diff выглядит интересно. не могли бы вы сообщить нам, где вы получили этот инструмент diff ?? - person earthdan; 22.02.2014