Site icon Embarcadero RAD Studio, Delphi, & C++Builder Blogs

Проблемы при смешивании объектов Classic и Clang: предупреждения компоновщика и повышение стабильности приложения

mixing classic and clang large size 2

Компоновщик 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, и это было задокументировано в онлайн-справке, но в то время не было опубликовано в блогах, мы добавили новое предупреждение компоновщика, чтобы помочь вам обнаружить такие ситуации.

Прежде чем показать решение, давайте кратко рассмотрим, что может произойти, если в ваших сборках есть эта ошибка.

Проблемы при несовпадении компиляторов

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

Ошибки времени компоновки

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

[crayon-676b0630cc9ee717427989/]

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

[crayon-676b0630cc9f7419383854/]

Ошибки времени выполнения

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

Не рекомендуется иметь странные ошибки компоновщика или странное поведение во время выполнения. Поэтому мы добавили предупреждение, чтобы проверить эту ситуацию.

Диагностика: предупреждение о новом компоновщике

RAD Studio / C ++ Builder 10.3.3 и новее предупреждает вас о смешивании clang и classic при компоновке. (Если возникают ошибки компоновщика, подобные описанным выше, это предупреждение выдается перед ними, поэтому вы увидите предупреждение перед любыми ошибками из-за проблемы.)

В сообщении говорится: «Предупреждение: несоответствие компилятора». а затем сообщает, что он ожидал и что обнаружил:

[crayon-676b0630cc9f9598056130/]

Итак, как компоновщик проверяет смешанные объекты и как он узнает, чего ожидать?

В приведенной выше ошибке у меня есть приложение VCL, связывающееся в статической библиотеке. Приложение VCL создано с помощью Clang. Библиотека построена на классическом. Приложение clang ссылается на библиотеку с помощью:

[crayon-676b0630cc9fb853870227/]

see documentation on linking with #pragma comment vs #link.

Ошибиться в несовпадении компиляторов очень легко. Как вы можете видеть на скриншоте справа, вы не можете легко определить, какой компилятор Win32 используется. Это то, что мы могли бы улучшить, но сейчас в нем указана целевая платформа, а не компилятор.

Теперь наш компилятор передает в каждый объект запись (небольшой фрагмент данных), в которой говорится, с каким компилятором он был построен (например, Clang Win32). При компоновке компоновщику предоставляется набор объектных файлов и библиотек в порядке, указанном в команде. линия. Он смотрит на первый объект, с которым связывается, и отмечает, что ожидает, что все последующие объекты будут построены с тем же компилятором, что и этот первый. Для каждого объекта, с которым он связан (и учитывая библиотеку, которая представляет собой просто набор объектов для каждого объекта в библиотеке), он проверяет, был ли он построен с помощью ожидаемого компилятора.

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

TLDR

Краткое резюме: объединение объектных файлов, созданных двумя компиляторами, в один двоичный файл — плохая идея. Компоновщик выдаст вам предупреждение, если вы это сделаете, и расскажет, что для чего построено, чтобы вы могли это исправить. Это устраняет проблемы компоновщика и проблемы со стабильностью приложения!

Дальнейшее чтение

Компоненты упаковки или библиотеки, написанные на классических и Clang компиляторах Win32 C ++ На
этой новой странице документации обсуждается предупреждение компоновщика, но также содержится немного больше информации. В нем рассматривается, как использовать clang или классические двоичные файлы, если вы разработчик приложений и создаете приложения с несколькими частями (возможно, связываясь с библиотекой C ++ с открытым исходным кодом, которую вы также создаете), а также есть еще один раздел для библиотеки разработчик (например, написание компонентов или библиотек и распространение их среди клиентов.)

Exit mobile version