Подтвердить что ты не робот

Как обрабатывать сторонние библиотеки с совершенно разными системами сборки?

С++ (и C, хотя это имеет значение меньше), стандарт утверждает, что все единицы перевода в программе должны иметь одно и то же определение; и это включает такие вещи, как коммутаторы компилятора. Например, на MSVС++ необходимо привязать к правильной версии библиотеки времени выполнения C (/MT versus /MD versus /MTd versus /MDd) во всех единицах перевода.

Однако есть несколько зависимостей сторонних разработчиков, которые мы хотели бы использовать, и есть несколько вещей:

  • Все они используют разные системы сборки (там есть autoconf, есть cmake, и есть тот, который, кажется, имеет свою собственную ручную вещь).
  • В системах сборки не все выставляются такие типы коммутаторов в их конфигурации, а те, которые жестко закодированы, устанавливаются по-разному в разных системах. (Например, одна библиотека заставляет /MD и /MDd, а другая - /MT и /MTd)

Мы не уверены, что лучший способ справиться с такими вещами. Мы обсудили следующие варианты:

  • Постройте нашу собственную систему сборки независимо от сторонних зависимостей.
    • PRO: Мы знаем, что все будет соответствовать
    • PRO: Мы знаем, что мы можем сделать кросс-платформенную поддержку правильным способом.
    • CON: Мы не знаем точно, как работают каждая из сторонних систем сборки.
    • CON: Много и много работы
    • CON: прерывается, если изменяется зависимость третьей стороны.
  • Попробуйте использовать сторонние системы сборки и попытайтесь изменить их, чтобы делать то, что нам нужно.
    • PRO: Кажется, меньше работы.
    • CON: Мы можем сломать стороннюю систему.
    • CON: прерывается, если изменяется зависимость третьей стороны.
    • CON: Заставляет нашу собственную сборку быть действительно сложной.

Мы не знаем, что делать; и мы не можем поверить, что мы одни в таких вопросах. Должны ли мы сделать один из этих вариантов выше или какую-то третью альтернативу, о которой я не думал?

4b9b3361

Ответ 1

Вам не нужно, чтобы все ваши библиотеки связывались с одной и той же средой выполнения. Предполагая, что они DLL, это только проблема, если они передают структуры данных ЭЛТ через границу DLL. Создание FILE* в DLL с использованием одной среды выполнения и использование ее из DLL, связанной с другой средой выполнения, является рецептом катастрофы. Вызов malloc или new из DLL с использованием одной среды выполнения, а free/delete из другого приведет к множеству проблем с потерей.

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

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

Итак, что мы делаем, в основном это:

  • по возможности, мы сами строим библиотеку. По большей части это означает, что мы можем с помощью довольно простых средств контролировать, с какой средой выполнения она должна ссылаться. Это может потребовать очень небольшого количества настройки системы сборки, но обычно это просто вопрос о том, нужно ли строить отладочную или выпускную сборку, для которой большинство систем сборки имеют параметры. (И если библиотека использует Visual Studio для своей системы сборки, мы стараемся обновить ее до 2010 года, когда это возможно).
  • мы используем собственную систему сборки библиотеки. Все остальное - всего лишь рецепт страдания. Вы хотите быть уверенным в том, что система сборки фактически хранится в синхронизации с исходным кодом библиотеки и самым простым способом обеспечить использование системы сборки, которая поставляется с исходным кодом.
  • Если это нецелесообразно для создания библиотеки, мы просто используем ее как есть, и тогда нам просто нужно распределить любую среду выполнения, с которой она связана. Мы стараемся избегать этого, но это достаточно безопасно, если нет другого варианта.
  • Когда мы создаем библиотеку, мы точно документируем, как это было сделано на нашей внутренней вики. Это огромная помощь, если нам нужно перейти на новую версию библиотеки или перестроить ее.

В настоящее время мы зависим от трех разных сеансов VS (2005, 2008 и 2010 гг.), что является большой проблемой для работы, но оно работает. И для одного или двух из них мы всегда используем версию выпуска, даже в отладочных сборках нашего собственного кода.

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

Конечно, вы должны свести к минимуму количество сторонних зависимостей, которые вы имеете, и когда вы выбираете стороннюю библиотеку, ее система построения обязательно должна быть фактором, который следует учитывать. Некоторые из них гораздо более болезненны, чем другие.

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

Ответ 2

Я предполагаю, что вы намеренно не упоминаете какие-либо конкретные библиотеки?

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

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

Итак, компиляция сторонней библиотеки - это то, что мы делаем только один раз для сторонней версии, и мы не обременяем нашу систему сборки сложностями построения сторонних библиотек.

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

Ответ 3

Вы правы - вы не одиноки в таких проблемах!

По нашему опыту, наиболее эффективная взаимосвязь зависимостей (фантастический способ сказать вручную копирование файлов, которые, как я полагаю), и изменение системы сборки сторонних разработчиков - особенно, если вы строите окна.

Несколько вещей, которые мы нашли полезными: -

Документируйте изменения, которые вы должны были применить (мы используем страницу вики) для конкретной версии, и включим любые требуемые шаги/зависимости (интерпретатор Perl, необходимый для создания OpenSSL), и запустите все/все включенные тесты перед использованием сборки.

Мы обнаружили, что переименование выходных libs таким образом, что они помечены в соответствии с ABI последовательно, действительно полезно здесь, а не с использованием имен, созданных третьей стороной.

так что сторонняя зависимость С++ X заканчивается в нашей структуре каталогов (привязана к svn) как

X/[version_number]/include (файлы заголовков для использования lib)

X/[version_number]/lib/Windows (встроенные вручную, протестированные и переименованные библиотеки)

например,

X-vc100.lib X-VC100-gd.lib

и т.д.

(мы фактически скопировали наше название из имен boost http://www.boost.org/doc/libs/1_49_0/more/getting_started/windows.html#library-naming, поскольку они казались совершенно разумными)

Затем конкретная зависимость сторонней стороны может быть выбрана вашей системой сборки (для VS мы используем унаследованный лист свойств со всеми зависимостями, названными как пользовательский макрос, поэтому можно просто добавить $(x_inc) в каталоги include для проекта и $(x_lib), добавленный в libs - эти макросы затем выбирают версию и abi, необходимые для этого конкретного проекта.

Ответ 4

Нет окончательного ответа, это зависит от того, как разработан интерфейс стороннего кода. Если интерфейс является узким, например, совместными непрозрачными типами данных, лучше их перестроить, используя собственную сборку и параметры. Вы должны проанализировать интерфейс и определить, как их интегрировать. С другой стороны, если интерфейс прост и может быть легко развязан, они могут быть построены как DLL и вызваны по требованию. Конечно, у вас будет другая версия библиотек C, загружаемых в приложение, и все они имеют разные экземпляры буферов io, управление памятью и т.д.

Если у вас есть исходный код, доступный вам, лучший выбор - инвестировать больше времени на интеграцию их в свою собственную сборку.