Как компоновщик C ++ узнает, какой .lib содержит какие функции? - PullRequest
15 голосов
/ 03 марта 2011

Например, в Boost.Я установил каталог include в MSVC ++ 2010 в корневой каталог Boost, и в моем исходном коде есть #include <boost/regex.hpp>.Я установил каталог library на boost\stage\lib, но там есть сотни файлов - по несколько для каждой библиотеки Boost и для boost :: regex:

libboost_regex-vc100-s-1_46.lib
libboost_regex-vc100-mt-gd-1_46.lib
libboost_regex-vc100-mt-1_46.lib
libboost_regex-vc100-mt-s-1_46.lib
libboost_regex-vc100-mt-s.lib
libboost_regex-vc100-s.lib
libboost_regex-vc100-mt.lib
libboost_regex-vc100-mt-gd.lib

Как MSVC узнаеткакой из всех файлов lib является правильным?Если он сканирует их все на предмет правильных сигнатур функций, означает ли это, что две разные библиотеки, скомпилированные из двух разных источников (не связанных друг с другом), которые могут определять функции с одинаковыми именами и параметрами, не могут находиться в одной папке библиотеки?

И как он узнает, что является правильным среди всех этих регулярных выражений .lib?И затем, каждый файл с 1_46 в имени файла кажется идентичным соответствующему файлу без, могу ли я безопасно удалить один из двух?

Ответы [ 3 ]

18 голосов
/ 03 марта 2011

В библиотеках boost используется некоторая dark magic для выбора библиотек для связи из заголовков и параметров компилятора. Я действительно не знаю всех кровавых подробностей, но вы можете взглянуть на заголовок boost / config / auto_link.hpp для дополнительной информации.

В частности, это, кажется, важная часть головоломки:

#  pragma comment(lib, BOOST_LIB_PREFIX BOOST_STRINGIZE(BOOST_LIB_NAME) "-" BOOST_LIB_TOOLSET BOOST_LIB_THREAD_OPT BOOST_LIB_RT_OPT "-" BOOST_LIB_VERSION ".lib")
5 голосов
/ 03 марта 2011

Большинство lib файлов имеют оглавление.Компоновщик ищет эту таблицу, когда ищет символ.Если символ не найден, он переходит к следующей библиотеке и так далее, пока не будут найдены все библиотеки.

Некоторые компоновщики могут решить создать оглавление из всех библиотек.Эта таблица будет содержать имя символа и библиотеку, с которой он связан.Это ускоряет поиск символов.

Порядок поиска зависит от производителя компоновщика.Для этого нет ни стандартов, ни требований.Линкер может осуществлять поиск по первым пришел, первым обслужен , как указано в командной строке; последняя указанная библиотека или другой метод.Проверьте документацию для критериев.

Также поищите в сети name mangling.Это метод, который компиляторы используют для разрешения конфликтов имен символов.

Наконец, компоновщики могут включать все функции в библиотеке, даже если используется только одна.Некоторые компоновщики включают только код для функции.Зависит от производителя линкера.Например, включает ли компоновщик всю библиотеку ввода-вывода при разрешении puts или он просто включает необходимые функции?Включение всей библиотеки ускоряет время сборки, но делает исполняемый файл огромным.Включение только необходимого кода замедляет процесс сборки, но уменьшает размер исполняемого файла.

В общем, фаза связывания является одной из самых быстрых частей процесса перевода.Если вас беспокоит время сборки, начните сборку в конце дня или отправляйтесь на прогулку после начала сборки.; -)

2 голосов
/ 03 марта 2011

Две библиотеки, содержащие одинаковые функции, не проблема. Компоновщик смотрит только на те библиотеки, на которые ему говорят. Если два из их содержат идентичные функции, это выдаст сообщение об ошибке (это на самом деле довольно часто, обычно из-за конфликта между статическим и динамическим связыванием со стандартной библиотекой).

Вы можете указать компоновщику, на какие библиотеки обращаться несколькими способами - в командной строке компоновщика (возможно, как генерируется IDE) и с помощью #pragma comment(lib, "libname.lib") - две наиболее распространенные.

...