Как я могу связать (или работать) две сторонние статические библиотеки, которые определяют одни и те же символы?
Я не могу быть единственным, кто столкнулся с этим.
У меня есть приложение на С++, которое необходимо связать с одной сторонней и другой статической библиотекой, установленной в SDK. SDK по какой-то ужасно расстраивающей причине перекомпилировал подмножество этой же сторонней библиотеки в свою собственную (переименованную) библиотеку lib, хотя сами символы называются одинаковыми, и они не инкапсулированы в пространство имен. Мое приложение зависит от той же сторонней библиотеки.
Я рассмотрел несколько вариантов, но, возможно, мне что-то не хватает, и, надеюсь, свежий взгляд поможет мне. Возможно, я рядом, и кто-то узнает следующий шаг для одного из них. Я буду перечислять то, что я пробовал, и недостатки каждого решения:
-
Связь с обоими.
Я получаю около 2500 строк предупреждений о переопределении символов/изменении размера и ошибок. Это когда я впервые обнаружил, что они определили одни и те же символы. Я пытаюсь перекомпилировать OpenSSL с g++ и переместить его в пространство имен на данный момент... см. Ниже...
-
Ссылка только на SDK.
Я получаю символы undefined, от которых зависит мой собственный код - это когда я обнаружил, что их перекомпиляция третьей стороны lib является подмножеством или, по крайней мере, была настроена с отключенным одним модулем.
-
Связывается только с третьей стороной lib.
У меня есть пара символов undefined, о которых сообщает SDK, - один из них на самом деле является #define в файле заголовка в третьей стороне lib, поэтому все ссылки в третьей стороне lib разрешают определение, но ссылки вне этого не. Я переместил это в файл c, который разрешает это, однако у меня все еще есть две нерешенные функции, которые я не могу найти нигде. Это самое близкое, что я получил до сих пор.
-
Разделите конфликтующие символы из одной библиотеки и ссылки в обоих.
Пока это не сработало. Это может быть проблема с версией между lib, статически связанной в SDK, и версиями, которые я пытался использовать сторонней lib, но похоже, что некоторые функции перемещались между символами, поэтому, удалив символ, я случайно удаляю функции, которые мне нужны в другом месте. Кажется, что нет идеального отображения между функциями в символах в SDK и функциями в символах в сторонней библиотеке. Возможно ли разрезать функции без необходимости ручной настройки адресов?
Я изучал символы в библиотеках с помощью:
nm -C --defined-only lib<name>.a
И извлечение целых объектов с помощью
ar -x lib<name>.a <objname>.o
Надеюсь, это также поможет другим, кто должен был связываться с сторонними библиотеками, которые конфликтуют друг с другом. Для специфики, сторонняя библиотека OpenSSL, а SDK Opsec - libcpopenssl.a является нарушителем lib в Opsec.
** РЕДАКТИРОВАТЬ. Возможно, поздняя запись может перекомпилировать OpenSSL с g++ и поместить все это в пространство имен, а затем связать обе библиотеки. Я сейчас пытаюсь... еще впереди...
Ответы
Ответ 1
Поиск в Google показывает, что SSL_get_peer_dh и DH_dup действительно являются дополнениями от libcpopenssl.a, и они также не существуют в моей копии OpenSSL. Таким образом, вам действительно нужно будет связать эту библиотеку. Смешивание обеих библиотек вместе (подход 4 выше) на двоичном уровне вряд ли сработает - OpenSSL очень разборчив в отношении своего ABI (обычно они имеют файлы .so с версией до младшего номера), поэтому вам должно быть очень повезло иметь .so что ABI-совместимый с их .a файлом.
Мое предложение - это вариант подхода 4, но на исходном уровне: у вас будет ссылка в Opsec libcpopenssl.a, так как это модифицированная версия OpenSSL, которая включает дополнительные символы (и, возможно, другие модификации), и захватить дополнительные функции, которые вам нужны из источников OpenSSL, и перекомпилировать эти объекты с помощью libcpopenssl.a, чтобы они могли использовать функции из версии Opsec. Если вы используете только несколько функций OpenSSL, которые не экспортируются libcpopenssl.a, это вполне выполнимо.
Конечно, это еще и громоздкий подход, но это гарантированный способ получить совместимость символов, конечно же, что Opsec SDK не внес семантические изменения в OpenSSL, что нарушит дополнительные функции OpenSSL, которые вы втягиваете в свои проект.
(Я новичок в StackOverflow, поэтому не знаю, соответствует ли это предложение правильному ответу, но у меня нет точек репутации, чтобы публиковать комментарии). Я удалю это, если это будет неуместно.)
Ответ 2
Если вам любопытно, 249 файлов были изменены в самой последней версии OpenSSL, чтобы получить ее для компиляции. Наиболее распространенной проблемой на сегодняшний день было обилие бросков указателей стиля С, в частности с void *. Теперь я вижу "reinterpret_cast" во сне.
Это не решило его в одиночку, но его все равно нужно полностью помещать в пространство имен, что означает изменение всех файлов снова, а также мои собственные внутренние ссылки на него. Я думаю, что я собираюсь передать это сейчас.
Спасибо за помощь всем.