Примечание. Это не повторяющийся вопрос, потому что ни один другой ответ не учитывает проблемы с несколькими определениями.
Я пытаюсь объединить две статические библиотеки в одну. (Это работает).
Затем преобразуйте эту статическую библиотеку в динамическую библиотеку. (Это не работает из-за множественной ошибки определения).
Я сделал публичное репо с примерами исходников.
Вот ключевые компоненты:
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
Я думал, что объединив две статические библиотеки в одну статическую библиотеку, архиватор уберет лишние символы.
Как мне объединить статические библиотеки в одну общую библиотеку, если есть вероятность конфликтов имен символов?
Вы собрали статическую библиотеку, но она не работает
Библиотека — это не что иное, как набор объектных файлов.
Какой экземпляр version()
вы ожидаете вызвать при ссылке на окончательную общую библиотеку?
Тег unix-ar содержит ряд вопросов о команде ar
и связывании библиотек, а ряд вопросов об объединении библиотек показаны в виде дубликатов на первой странице вывода. (Долгое время тег был просто ar , но люди дополненной реальности в конце концов добились своего, и им был предоставлен ar — вероятно, примерно в то же время, когда он перестал быть столь убедительной областью вопросов, как это было.)
@Galik Я понимаю твою точку зрения. Я действительно не хочу, чтобы эта функция версии вообще вызывалась конечным приложением. Я хочу, чтобы он оставался внутренним методом исходной библиотеки. Однако я думаю, что подход, который я использую, не может этого достичь.
@CraigDavid Тогда вы можете пометить функцию как static
, как в static int version()
. Это означает, что его могут вызывать только функции в одной и той же единице перевода (и, следовательно, в библиотеке). Он не будет виден внешнему компоновщику.
Странный. Я думал, что ar
будет зарезервирован для вопросов о пиратстве.
Вы не можете использовать совокупную статическую библиотеку, если у вас есть код, который вызывает как return_one()
, так и return_zero()
, потому что у вас возникнут проблемы с повторяющимися символами с функциями version()
.
Как вы решите, какую version()
функцию вы хотите вызвать, если вы свяжетесь с совокупной библиотекой?
Вам придется решить эту проблему — и это, вероятно, означает что-то вроде добавления ко всем функциям из return_zero.cpp
префикса, такого как r0_
(или, в C++, помещения их в namespace return_zero { … }
), и — для симметрии, если не лучше причина — добавление ко всем функциям из return_one.cpp
префикса типа r1_
(или помещение их в namespace return_one { … }
). Затем ваш вызывающий код будет использовать имена с префиксом (или префикс функций с соответствующим именем пространства имен).
«Примечание: это не повторяющийся вопрос, потому что ни один другой ответ не учитывает проблемы с несколькими определениями». - Я почти уверен, что это ложь.