Как С++-компоновщик знает, какой .lib содержит какие функции?
Например, в Boost. Я установил каталог include в MSVС++ 2010 в корневой каталог Boost и #include <boost/regex.hpp>
в моем исходном коде. Я установил каталог библиотеки 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 является правильным? Если он сканирует все из них на правильные сигнатуры функций, означает ли это, что 2 разных lib, скомпилированных из двух разных источников (не связанных друг с другом), которые могут определять функции с одинаковыми именами и параметрами, не могут находиться в одной папке lib?
И как он узнает, что является правильным среди всех этих разных регулярных выражений .lib? И тогда каждый файл с 1_46
в своем имени файла, похоже, идентичен соответствующему файлу без него, могу ли я безопасно удалить один из двух?
Ответы
Ответ 1
Библиотеки boost используют некоторую темную магию для выбора библиотек для ссылок из заголовков и параметров компилятора. Я не знаю всех подробностей, но вы можете посмотреть заголовок 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")
Ответ 2
В большинстве файлов lib
содержится таблица. Линкер ищет эту таблицу, когда ищет символ. Если символ не найден, он переходит к следующей библиотеке и так далее, пока не будут найдены все библиотеки.
Некоторые линкеры могут решить создать оглавление из всех библиотек. Эта таблица будет содержать имя символа и связанную с ним библиотеку. Это ускоряет поиск символов.
Порядок поиска зависит от производителя компоновщика. Для этого нет стандартов и требований. Линкером может выполняться поиск с первого взгляда, сначала выполняется, как указано в командной строке; указанную последнюю библиотеку или какой-либо другой метод. Проверьте документацию по критериям.
Также найдите в Интернете name mangling
. Это метод, используемый компиляторами для разрешения конфликтов имен.
Наконец, линкеры могут включать в себя все функции в библиотеке, даже если используется только один. Некоторые линкеры включают только код для функции. Зависит от производителя Linker. Например, содержит ли компоновщик всю библиотеку ввода-вывода при разрешении puts
или просто включает в себя необходимые функции? Включение всей библиотеки ускоряет время сборки, но делает исполняемый файл огромным. Включение только необходимого кода замедляет процесс сборки, но уменьшает размер исполняемого файла.
В общем, фаза связывания является одной из более быстрых частей процесса перевода. Если вы беспокоитесь о времени сборки, начните сборку в конце дня или отправитесь на прогулку после начала сборки.; -)
Ответ 3
Две библиотеки, содержащие идентичные функции, не являются проблемой. Компонент только просматривает библиотеки, на которые он сказал, чтобы посмотреть. Если два из них содержат одинаковые функции, они выдадут сообщение об ошибке (это на самом деле довольно распространено, обычно из-за конфликта между статической и динамической привязкой со стандартной библиотекой).
Вы можете рассказать компоновщику, какие библиотеки нужно искать несколькими способами - в командной строке компоновщика (возможно, сгенерированной IDE) и через #pragma comment(lib, "libname.lib")
являются наиболее распространенными из них.