связывание общей библиотеки со статикой с помощью CMake

cmake 2.8
gcc (GCC) 4.8.1

Редактировать ----------

Обертывание статических библиотек в whole-archive работает для всех библиотек, кроме pjmedia-videodev. Проблема в том, что когда я пытаюсь выполнить сборку, я получаю следующую ошибку.

cbar_factory_init': colorbar_dev.c:(.text+0x2a0): undefined reference to pjmedia_format_init_video'

Привет,

Я создал общую библиотеку, и мне нужно связать эту библиотеку примерно с 10 статическими библиотеками. Затем я связываю свой исполняемый файл с общей библиотекой.

Мой вопрос в том, что когда я запускаю make, он не может подключиться, так как он также хочет статические библиотеки. Цель - создать оболочку для статических библиотек. Таким образом, исполняемый файл должен связываться только с одной общей библиотекой. Поскольку я связываю общую библиотеку со статикой, статика автоматически станет частью исходного кода общей библиотеки.

Только кодируйте sippnets, чтобы сделать это коротким. В моем CMakeLists.txt, который создает общую библиотеку и связывает статические библиотеки:

add_library(app_module_sip SHARED app_module_sip_init.c)

 set(PJSIP_LIBRARIES
  g7221codec
  gsmcodec
  ilbccodec
  milenage
  pj
  pjlib-util
  pjmedia
  pjmedia-codec
  pjmedia-audiodev
  pjmedia-videodev
  pjnath
  pjsip
  pjsip-simple
  pjsip-ua
  pjsua
  portaudio
  resample
  speex
  srtp
)

target_link_libraries(app_module_sip pthread m uuid nsl rt asound crypto ssl ${PJSIP_LIBRARIES})

Теперь мой CMakeLists.txt, который делает исполняемый файл

add_executable(app sip_test.c)

target_link_libraries(app app_module_sip)

Правильно ли это то, что я здесь делаю? Я не хочу связывать исполняемый файл со статическими библиотеками. Просто единственная разделяемая библиотека, поскольку это моя оболочка, в которой я буду вызывать функции.

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

Большое спасибо за любые предложения,


person ant2009    schedule 02.10.2013    source источник


Ответы (3)


Я попытался проверить свое решение, но ваш файл CMakeLists.txt у меня работал без каких-либо изменений. Тем не менее, глядя на этот вопрос: Включить статическую библиотеку в динамическую библиотеку, кажется что ты должен попробовать

target_link_libraries(app_module_sip ... ssl -Wl,-whole-archive ${PJSIP_LIBRARIES} -Wl,-no_whole-archive)

(прокрутите до конца, это длинная строка)

person Roberto    schedule 04.10.2013
comment
Это сработало для меня. Однако моя статическая библиотека, которую я пытался связать, не удалась с помощью libpjmedia-videodev.a (colorbar_dev.o): In function cbar_factory_init': colorbar_dev.c:(.text+0x2a0): undefined reference to pjmedia_format_init_video '. Однако, если я удалю статическую библиотеку pjmedia-videodev, все будет компилироваться, строиться и запускаться. Не уверен, почему эта библиотека потерпела неудачу. На данный момент мне не нужно заниматься видео-персоналом, но позже он мне понадобится. Спасибо за предложение. - person ant2009; 04.10.2013

Это не так просто.

Вы можете использовать «-Wl, - all-archive» или «-Wl, - export-all-symbols» в зависимости от вашей платформы, но нет хорошего кроссплатформенного способа сделать это. Все работает по-другому, и Windows играет в совершенно другую игру, используя lib.exe.

Вероятно, вы захотите сделать что-то вроде этого:

http://www.mail-archive.com/[email protected]/msg01890.html

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

person Doug    schedule 04.10.2013
comment
@ Дуг, это была статья 2006 года, и -all и -notall больше не существуют. Моя текущая версия ld - «GNU ld version 2.23.51.0.1-10.fc18», я полагаю, что в какой-то момент она была удалена. Спасибо. - person ant2009; 04.10.2013
comment
@ ant2009 нет, я имел ввиду, используйте IF ($ {CMAKE_SYSTEM} MATCHES IRIX) ... IF (APPLE) ... IF (WIN32) ... и т. д. Вам необходимо вручную указать разные флаги компиляции для каждой платформы, которую вы хотите поддерживать. Нет универсального кроссплатформенного способа сделать это. - person Doug; 06.10.2013

# Location for shared library
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/libs)

# Create shared library
add_library(app_module_sip SHARED app_module_sip_init.c)

# compile and link for 32 bit mode
set_target_properties(app_module_sip PROPERTIES COMPILE_FLAGS "-m32" LINK_FLAGS "-m32")

# PJSIP static libraries
set(PJSIP_LIBRARIES
  pjsua
  pjsip-ua
  pjsip-simple
  pjsip
  pjmedia-codec
  pjmedia-videodev
  pjmedia
  pjmedia-audiodev
  pjnath
  pjlib-util
  resample
  milenage
  srtp
  gsmcodec
  speex
  ilbccodec
  g7221codec
  portaudio  
  pj
)

# Wrap the static libraries in to the shared library
target_link_libraries(app_module_sip -Wl,--start-group ${PJSIP_LIBRARIES} -Wl,--end-group 
  m uuid nsl rt pthread asound crypto ssl)

Необходимо обернуть библиотеки pjsip следующей командой компоновщика -Wl, - start-group * .a -Wl, - end-group.

Это решило мою проблему.

person ant2009    schedule 09.10.2013
comment
Когда я связываю app_module_sip с myapp, CMake, кажется, добавляет все дочерние библиотеки, такие как pjsua в дополнение к app_module_sip, и дублированные объекты портят статическую инициализацию, не говоря уже о раздутом двоичном размере. - person nodakai; 20.03.2017