Объединение двух статических библиотек в одну динамическую библиотеку без множественных определений

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

Я пытаюсь объединить две статические библиотеки в одну. (Это работает).

Затем преобразуйте эту статическую библиотеку в динамическую библиотеку. (Это не работает из-за множественной ошибки определения).

Я сделал публичное репо с примерами исходников.

Вот ключевые компоненты:

return_zero.cpp

int return_zero() { return 0; }
int version() { return 0; }

return_one.cpp

int return_one() { return 1; }
int version() { return 1; }

Обратите внимание, что у каждой библиотеки есть своя функция version.

Я могу встроить каждую из них в свои собственные статические библиотеки. libreturn_zero.a и libreturn_one.a.

Я могу объединить их в libreturn.a с помощью утилиты ar.

Когда я выгружаю символы с помощью утилиты nm:

$ nm -C libreturn.a 

return_one.cpp.o:
0000000000000000 T return_one()
000000000000000b T version()

return_zero.cpp.o:
0000000000000000 T return_zero()
000000000000000b T version()

Затем я пытаюсь преобразовать эту совокупную статическую библиотеку в разделяемую библиотеку.

Я использую фиктивный исходный файл и связываю libreturn.a с помощью флага компоновщика --whole-archive.

Вот как выглядит команда ссылки:

g++ -fPIC -shared -Wl,-soname,libreturn.so -o libreturn.so "dummy.cpp.o" -Wl,--push-state,--whole-archive libreturn.a -Wl,--pop-state

Вышеприведенное выглядит так, как я хочу, но оно не работает, потому что существует два определения версии.

libreturn.a(return_zero.cpp.o): In function `version()':
return_zero.cpp:(.text+0xb): multiple definition of `version()'
libreturn.a(return_one.cpp.o):return_one.cpp:(.text+0xb): first defined here
collect2: error: ld returned 1 exit status
CMakeFiles/return-shared.dir/build.make:97: recipe for target 'libreturn.so' failed
make[2]: *** [libreturn.so] Error 1

Я думал, что объединив две статические библиотеки в одну статическую библиотеку, архиватор уберет лишние символы.

Как мне объединить статические библиотеки в одну общую библиотеку, если есть вероятность конфликтов имен символов?

«Примечание: это не повторяющийся вопрос, потому что ни один другой ответ не учитывает проблемы с несколькими определениями». - Я почти уверен, что это ложь.

Jesper Juhl 31.03.2023 23:40

Вы собрали статическую библиотеку, но она не работает

Mooing Duck 31.03.2023 23:40

Библиотека — это не что иное, как набор объектных файлов.

Jesper Juhl 31.03.2023 23:44

Какой экземпляр version() вы ожидаете вызвать при ссылке на окончательную общую библиотеку?

Galik 31.03.2023 23:45

Тег unix-ar содержит ряд вопросов о команде ar и связывании библиотек, а ряд вопросов об объединении библиотек показаны в виде дубликатов на первой странице вывода. (Долгое время тег был просто ar , но люди дополненной реальности в конце концов добились своего, и им был предоставлен ar — вероятно, примерно в то же время, когда он перестал быть столь убедительной областью вопросов, как это было.)

Jonathan Leffler 31.03.2023 23:50

@Galik Я понимаю твою точку зрения. Я действительно не хочу, чтобы эта функция версии вообще вызывалась конечным приложением. Я хочу, чтобы он оставался внутренним методом исходной библиотеки. Однако я думаю, что подход, который я использую, не может этого достичь.

CraigDavid 01.04.2023 00:05

@CraigDavid Тогда вы можете пометить функцию как static, как в static int version(). Это означает, что его могут вызывать только функции в одной и той же единице перевода (и, следовательно, в библиотеке). Он не будет виден внешнему компоновщику.

Galik 01.04.2023 00:07

Странный. Я думал, что ar будет зарезервирован для вопросов о пиратстве.

user4581301 01.04.2023 00:09
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
8
114
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы не можете использовать совокупную статическую библиотеку, если у вас есть код, который вызывает как return_one(), так и return_zero(), потому что у вас возникнут проблемы с повторяющимися символами с функциями version().

Как вы решите, какую version() функцию вы хотите вызвать, если вы свяжетесь с совокупной библиотекой?

Вам придется решить эту проблему — и это, вероятно, означает что-то вроде добавления ко всем функциям из return_zero.cpp префикса, такого как r0_ (или, в C++, помещения их в namespace return_zero { … }), и — для симметрии, если не лучше причина — добавление ко всем функциям из return_one.cpp префикса типа r1_ (или помещение их в namespace return_one { … }). Затем ваш вызывающий код будет использовать имена с префиксом (или префикс функций с соответствующим именем пространства имен).

Другие вопросы по теме