![mixing classic and clang large size | Embarcadero RAD Studio Delphi C++Builder Blogs mixing classic and clang large size 2](https://i0.wp.com/blogs.embarcadero.com/wp-content/uploads/2020/08/mixing-classic-and-clang-large-size-6958690.jpg?resize=1140%2C694&ssl=1)
Компоновщик C ++ Builder предупредит вас, когда вы смешиваете объектные файлы, связанные классическим и clang вместе, помогая вам избежать ошибок компоновщика или времени выполнения.
Сегодня, в 2020 году, мы рекомендуем использовать современные компиляторы Clang, особенно с той работой, которую мы проделали для Win64 (например, совершенно новый отладчик), и улучшениями RTL, чтобы упростить обновление с классической версии. Однако многие клиенты обновляются поэтапно: сначала с классического Win32 до Clang Win32, а затем добавление Win64. Фактически, мы часто прямо рекомендуем это как стратегию обновления, чтобы сначала перейти на Clang, а затем на Win64, в два этапа.
Однако при переходе от классических компиляторов к clang возникает общая проблема. Объектные файлы (библиотеки .obj и .lib), созданные классическим компилятором Win32 и компилятором Clang, не совместимы друг с другом на двоичном уровне. (И classic, и clang могут связываться с Delphi, но classic и clang не могут связываться друг с другом.) Если вы попытаетесь создать приложение, в котором некоторые части построены с помощью Clang, а некоторые — с классическим смешением, вы можете ожидать чего угодно от ошибок компоновщика. к нестабильности во время выполнения. Тем не менее, это легко сделать случайно, как при обновлении, так и при добавлении новой библиотеки или EXE в ваш проект.
В версии 10.3.3, и это было задокументировано в онлайн-справке, но в то время не было опубликовано в блогах, мы добавили новое предупреждение компоновщика, чтобы помочь вам обнаружить такие ситуации.
Прежде чем показать решение, давайте кратко рассмотрим, что может произойти, если в ваших сборках есть эта ошибка.
Table of Contents
Проблемы при несовпадении компиляторов
В версии 10.3.3 и новее вы получите предупреждение компоновщика — см. Ниже — перед любым из следующих событий. Но если вы используете старую версию, до того, как мы добавили предупреждение, диагностирующее проблему, вы могли увидеть только следующие ошибки. Они появляются при связывании приложения.
Ошибки времени компоновки
Когда приложение, созданное с помощью цепочки инструментов Clang, связано с классической библиотекой, вы можете увидеть следующие ошибки:
1 2 3 |
[ilink32 Error] Error: Unresolved external '__InitExceptBlockLDTC' [ilink32 Error] Error: Unresolved external '_ThrowExceptionLDTC' Error: Unresolved external '_CatchCleanup()' |
Когда приложение, созданное с помощью классической цепочки инструментов, связано с библиотекой, созданной с помощью Clang, вы можете увидеть следующие ошибки:
1 2 3 4 5 6 7 8 9 |
Error: Unresolved external '___seh_personality_v0' Error: Unresolved external '__Unwind_SjLj_Register' Error: Unresolved external 'std::_Xbad_alloc()' Error: Unresolved external '___cxa_begin_catch' Error: Unresolved external '___cxa_rethrow' Error: Unresolved external '___cxa_end_catch' Error: Unresolved external '__Unwind_SjLj_Unregister' Error: Unresolved external '__Unwind_Resume' Error: Unresolved external '___cpp_terminate' |
Ошибки времени выполнения
В некоторых случаях вы можете вообще не увидеть ошибок компоновщика, и вы запустите свое приложение. Скорее всего, в какой-то момент ваше приложение выйдет из строя, и будет сложно понять, почему, потому что код выглядит нормально. На самом деле это будет из-за того, что два разных компилятора делают что-то по-разному — разная структура памяти, выравнивание, ожидания библиотеки времени выполнения, обработка исключений, всевозможные возможные различия.
Не рекомендуется иметь странные ошибки компоновщика или странное поведение во время выполнения. Поэтому мы добавили предупреждение, чтобы проверить эту ситуацию.
Диагностика: предупреждение о новом компоновщике
RAD Studio / C ++ Builder 10.3.3 и новее предупреждает вас о смешивании clang и classic при компоновке. (Если возникают ошибки компоновщика, подобные описанным выше, это предупреждение выдается перед ними, поэтому вы увидите предупреждение перед любыми ошибками из-за проблемы.)
В сообщении говорится: «Предупреждение: несоответствие компилятора». а затем сообщает, что он ожидал и что обнаружил:
1 |
Warning: Compiler mismatch. Module 'Z:RAD STUDIO PROJECTSDEMOS AND WEBINARSMIXING CLASSIC AND CLANGWIN32DEBUGMYSTATICLIB.LIB|Unit1' built with bcc32 compiler; expected the bcc32c compiler because of 'Z:RAD STUDIO PROJECTSDEMOS AND WEBINARSMIXING CLASSIC AND CLANGWIN32DEBUGVCLAPP.OBJ' |
Итак, как компоновщик проверяет смешанные объекты и как он узнает, чего ожидать?
В приведенной выше ошибке у меня есть приложение VCL, связывающееся в статической библиотеке. Приложение VCL создано с помощью Clang. Библиотека построена на классическом. Приложение clang ссылается на библиотеку с помощью:
1 |
#pragma comment(lib, "MyStaticLib") |
⸺ see documentation on linking with #pragma comment vs #link.
![mixingclassicandclangprojectmanager1 | Embarcadero RAD Studio Delphi C++Builder Blogs](https://i0.wp.com/blogs.embarcadero.com/wp-content/uploads/2020/08/mixing-classic-and-clang-project-manager-1.png?resize=207%2C265&ssl=1)
Ошибиться в несовпадении компиляторов очень легко. Как вы можете видеть на скриншоте справа, вы не можете легко определить, какой компилятор Win32 используется. Это то, что мы могли бы улучшить, но сейчас в нем указана целевая платформа, а не компилятор.
Теперь наш компилятор передает в каждый объект запись (небольшой фрагмент данных), в которой говорится, с каким компилятором он был построен (например, Clang Win32). При компоновке компоновщику предоставляется набор объектных файлов и библиотек в порядке, указанном в команде. линия. Он смотрит на первый объект, с которым связывается, и отмечает, что ожидает, что все последующие объекты будут построены с тем же компилятором, что и этот первый. Для каждого объекта, с которым он связан (и учитывая библиотеку, которая представляет собой просто набор объектов для каждого объекта в библиотеке), он проверяет, был ли он построен с помощью ожидаемого компилятора.
![mixingclassicandclang1 | Embarcadero RAD Studio Delphi C++Builder Blogs](https://i0.wp.com/blogs.embarcadero.com/wp-content/uploads/2020/08/mixing-classic-and-clang-1.png?resize=207%2C107&ssl=1)
В противном случае выдается указанное выше предупреждение, которое вы также можете увидеть на изображении справа. Вы можете видеть, что он перечисляет ошибочный объект и то, с чем он был построен, а также объясняет, почему он искал другой компилятор. Это предназначено, чтобы помочь вам диагностировать настройку сборки.
TLDR
Краткое резюме: объединение объектных файлов, созданных двумя компиляторами, в один двоичный файл — плохая идея. Компоновщик выдаст вам предупреждение, если вы это сделаете, и расскажет, что для чего построено, чтобы вы могли это исправить. Это устраняет проблемы компоновщика и проблемы со стабильностью приложения!
Дальнейшее чтение
Компоненты упаковки или библиотеки, написанные на классических и Clang компиляторах Win32 C ++ На
этой новой странице документации обсуждается предупреждение компоновщика, но также содержится немного больше информации. В нем рассматривается, как использовать clang или классические двоичные файлы, если вы разработчик приложений и создаете приложения с несколькими частями (возможно, связываясь с библиотекой C ++ с открытым исходным кодом, которую вы также создаете), а также есть еще один раздел для библиотеки разработчик (например, написание компонентов или библиотек и распространение их среди клиентов.)
Design. Code. Compile. Deploy.
Start Free Trial Upgrade Today
Free Delphi Community Edition Free C++Builder Community Edition