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

CMake и статическая привязка

Я использую CMake в проекте, и я пытаюсь статически связывать некоторые библиотеки. Я установил:

set(BUILD_SHARED_LIBS OFF)
set(CMAKE_EXE_LINKER_FLAGS "-static-libgcc -static-libstdc++ -static")
set_target_properties(icarus PROPERTIES LINK_SEARCH_END_STATIC 1)

И я убедился, что при поиске фактических библиотек у меня есть их версия .a.

В настоящее время проект импортирует:

libPocoNet.a 
libPocoUtil.a 
libPocoXML.a 
libPocoFoundation.a 
libmysqlclient.a 
libmysqlpp.a 
libcrypto++.a 
CUDA

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

set(GCC_CXX_FLAGS ${GCC_CXX_FLAGS} "-static-libgcc -static-libstdc++ -static")

Но безрезультатно. Хотя во время компиляции я не получаю никаких проблем, ссылка связывает много << → undefined ссылок для вызовов, найденных в указанных выше библиотеках, например:

undefined reference to `mysql_thread_init'
undefined reference to `mysql_real_query'
undefined reference to `pthread_mutex_unlock'
undefined reference to `Poco::ErrorHandler::handle()'

Не в этом конкретном порядке и многочисленные ошибки для каждой библиотеки.

Посмотрев на последнюю строку GCC, я вижу:

/usr/bin/c++   -g -g  -static-libgcc -static-libstdc++ -static [list of *.cpp files]
-o icarus -rdynamic /usr/local/lib/libPocoFoundation.a /usr/local/lib/libPocoNet.a
/usr/local/lib/libPocoUtil.a /usr/local/lib/libPocoXML.a 
-Wl,-Bstatic -lmysqlclient -lmysqlpp -lcrypto++

Это заставляет меня задаться вопросом:

  • Почему библиотеки Poco связаны как -динамические, а флаг -Wl -Bstatic отсутствует? Как будто они пропускаются/исключаются из статической связи.
  • mysqlclient, mysqlpp и crypto ++, похоже, установлены для статической привязки, но я все равно получаю ошибки.

Итак, может кто-нибудь, пожалуйста, объясните мне:

  • Как настроить частичную статическую связь с помощью CMake
  • Является ли CMAKE_EXE_LINKER_FLAGS единственным, который мне нужно установить?
  • Должен ли я форсировать статические ссылки для упомянутых библиотек, но не для всего проекта?

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

4b9b3361

Ответ 1

Мне удалось решить мою проблему, используя следующее:

#Dynamic/Shared Libs
...
#Static start
set_target_properties(icarus PROPERTIES LINK_SEARCH_START_STATIC 1)
set_target_properties(icarus PROPERTIES LINK_SEARCH_END_STATIC 1)
set(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
#Static Libs
...
#Set Linker flags
set(CMAKE_EXE_LINKER_FLAGS "-static-libgcc -static-libstdc++")

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

Пока порядок статических библиотек верен, и до тех пор, пока выполняются зависимости статических библиотек, я получаю ELF, который загружает то, что является динамическим (т.е. в моем случае mysqlclient, libmysql ++) и статическим все остальное ( crypto ++, PocoNet, PocoUtil, PocoXML, PocoFoundation).

Имейте в виду, что статические связанные библиотеки имеют свои собственные зависимости. Изучая мое приложение отладки, используя приложение readelf -d, я вижу:

Dynamic section at offset 0x508f88 contains 28 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [libmysqlpp.so.3]
 0x0000000000000001 (NEEDED)             Shared library: [libmysqlclient.so.18]
 0x0000000000000001 (NEEDED)             Shared library: [libm.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [ld-linux-x86-64.so.2]
 0x0000000000000001 (NEEDED)             Shared library: [libpthread.so.0]

Я знаю, что pthread импортируется Poco:: Runnable, libm для математических операций и т.д. Я до сих пор не подозреваю, что это правильный способ использования CMake для частичного статического связывания.

В случае упакованных библиотек Debian, таких как crypto ++, mysql ++, mysqlclient, просто поиск библиотеки *.a работал, но в случае Poco Libraries, который только дал мне полный путь и имя библиотеки, но не флаг -Bdynamic может быть отключен только с помощью указанных выше строк.

Примечание: Poco не может быть связан статически, без -static-libstdc++

Я надеюсь, что это поможет кому-то застрять в чем-то подобном.

Ответ 2

Как настроить статическую связь с помощью CMake

Ну... вы не делаете:) Это не то, как работает CMake: в CMake вы сначала находите абсолютный путь библиотеки, а затем ссылаетесь на него с target_link_libraries.

Итак, если вы хотите установить ссылку на статическую библиотеку, вам необходимо выполнить поиск этой статической библиотеки:

find_library(SOMELIB libsomelib.a)

вместо:

find_library(SOMELIB somelib)