Почему в MSVC так много библиотек и почему я должен перекомпилировать код снова? - PullRequest
0 голосов
/ 24 декабря 2009

В каждой платформе есть различные версии данной библиотеки: многопоточная, отладочная, динамическая и т. Д.

Поправьте меня, если я ошибаюсь, но в Linux объект может связываться с любой версией библиотеки просто отлично, независимо от того, как она скомпилирована. Например, нет необходимости использовать какие-либо специальные флаги во время компиляции, чтобы указать, будет ли в конечном итоге ссылка на динамическую или статическую версию библиотек времени выполнения (пояснение: я не говорю о создании динамические / статические библиотеки, я говорю о ссылках на них - так что -fPIC не применяется). То же самое касается отладочной или оптимизированной версии библиотек.

Почему в MSVC (Windows в целом с другими компиляторами. Верно?) Мне нужно каждый раз перекомпилировать код для связи с различными версиями библиотек? Я говорю о флагах / MD, / MT, / MTd, / MDd и т. Д. Код на самом деле использует разные системные заголовки каждый раз. Если так, то почему?

Я был бы очень признателен за любые ссылки на надежную документацию, в которой обсуждаются эти вопросы библиотеки в Windows для программиста C / C ++.

спасибо!

Ответы [ 3 ]

4 голосов
/ 10 января 2010

Настройка компилятора мало что делает, кроме простого изменения некоторых определений макросов. Заголовочные файлы c-runtime его microsoft, которые изменяют свое поведение в зависимости от выбранной среды выполнения.

Во-первых, файлы заголовков используют директиву # pragma для встраивания в объектный файл директивы, определяющей, какой файл .lib следует включить, выбирая одно из: msvcrt.lib, msvcrtd.lib, libcmt.lib и mibcmtd.lib

Директивы выглядят так

#ifdef <release dll runtime>
#pragma comment(lib,"msvcrt.lib")
#endif

Затем он также изменяет определение макроса, используемое во всех функциях c-rt, которое добавляет директиву __declspec(dllimport), если была выбрана среда выполнения dll. эффект этой директивы - изменить импортированный символ, скажем, с '_strcmp' на '__imp__strcmp'.

Библиотеки импорта dll (msvcrt.lib и msvcrtd.lib) экспортируют свои символы (в компоновщик) как __imp_<function name>, что означает, что в мире Visual C ++, после того как вы скомпилировали код для связи со средами выполнения dll Вы не можете передумать - они НЕ будут связываться со статической средой выполнения. Конечно, это не так - библиотеки импорта dll на самом деле экспортируют свои публичные символы обоими способами: с префиксом __imp_ и без него. Это означает, что код, созданный на основе статической среды выполнения, МОЖЕТ позднее быть связан с связью с DLL или статической средой выполнения.

Если вы создаете статическую библиотеку для других потребителей, вы должны убедиться, что в настройках вашего компилятора указаны:

  1. Одна из статических настроек библиотеки , чтобы пользователи вашего .lib могли сами выбирать, какое c-runtime использовать, и
  2. Установите флажок ' Пропустить имя библиотеки по умолчанию ' (/ Zl). Это говорит компилятору игнорировать директивы #pragma comment(lib,..., поэтому файлы obj и получающаяся библиотека не имеют какой-либо неявной зависимости во время выполнения. Если вы этого не сделаете, пользователи вашей библиотеки, выбравшие другой параметр времени выполнения, увидят непонятные сообщения о дубликатах символов в libc.lib и msvcrt.lib, которые им придется обойти, используя флаг игнорирования библиотек по умолчанию.
1 голос
/ 24 декабря 2009

Использование этих опций компилятора имеет два эффекта. Автоматически #define макрос, который может использоваться заголовочными файлами (и вашим собственным кодом) для разных целей. Это влияет только на небольшую часть времени выполнения C, и вы можете проверить заголовки, чтобы увидеть, происходит ли это в вашем случае.

Другое дело, что компилятор C ++ встраивает комментарий в ваш объектный файл, который говорит компоновщику автоматически включать конкретный вариант среды выполнения MSVC, независимо от того, указана ли эта библиотека во время компоновки или нет.

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

Вы можете отключить автоматическую компоновку закомментированного варианта времени выполнения c, передав /nodefaultlib компоновщику. А затем укажите другой вариант времени выполнения c. Это будет работать, если вы будете осторожны, чтобы не зависеть от #defines для _MT и _DLL (имейте в виду, что стандартные заголовки C могут также смотреть на них).

Я не рекомендую этого, но если у вас есть причина для этого, в большинстве случаев ее можно заставить работать.

Если вы хотите узнать, какие части заголовочных файлов C ведут себя по-разному, вам просто нужно найти _MT и _DLL в заголовках и посмотреть.

0 голосов
/ 24 декабря 2009

Все опции используют одинаковые заголовочные файлы, однако все они подразумевают разные #define, которые влияют на заголовочные файлы. Поэтому их нужно перекомпилировать.

Переключатели также ссылаются на соответствующую библиотеку, но перекомпиляция не из-за связывания.

Смотрите здесь для списка того, что определено, когда вы используете каждый.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...