使用CMake链接静态库的共享库

5
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 命令时,由于它需要静态库,因此链接失败。目的是为静态库创建一个包装器,这样可执行文件只需链接一个共享库。由于我正在将共享库与静态库链接,因此静态库将自动成为共享库源代码的一部分。

以下是简短的代码片段。 在我的 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)

我在这里做的是否正确。我不想将可执行文件与静态库链接,只需使用单个共享库作为我的包装器,我将在其中调用函数。

如果在生成可执行文件时链接所有静态库,则可以正常链接,但这不是我想要的结果。

非常感谢任何建议,

3个回答

3

我试着测试了我的解决方案,但你的CMakeLists.txt对我来说没有任何改变就可用了。不过,看看这个问题:如何在动态库中包含静态库,似乎你应该尝试

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

(滚动到底部,这是一行很长的代码)


那对我有用。然而,我尝试链接的静态库失败了,出现了libpjmedia-videodev.a(colorbar_dev.o):在函数“cbar_factory_init”中: colorbar_dev.c:(.text+0x2a0):对“pjmedia_format_init_video”的未定义引用。但是,如果我删除静态库pjmedia-videodev,一切都可以编译、构建和运行。不确定为什么那个库失败了。目前我不需要做任何视频工作,但以后我会需要它。感谢您的建议。 - ant2009

2
“这并不是那么简单。您可以尝试使用'-Wl,--whole-archive'或'-Wl,--export-all-symbols',具体取决于您的平台,但没有一种好的跨平台方法来实现此功能。每个平台都有不同的实现方式,而在Windows中使用lib.exe则完全不同。您可能想要做类似于以下的事情:”

http://www.mail-archive.com/cmake@cmake.org/msg01890.html

"...并逐个为您想要支持的平台添加特定的支持。"

@ Doug,那篇文章是2006年的,-all和-notall已经不存在了。我的当前ld版本是“GNU ld version 2.23.51.0.1-10.fc18”。我想这些选项在某个时候被删除了。谢谢。 - ant2009
@ant2009 不,我的意思是使用IF("${CMAKE_SYSTEM}" MATCHES IRIX) ... IF(APPLE) ... IF(WIN32) ...等。也就是说,您必须手动指定要支持的每个平台的不同编译标志。没有跨平台的“通用”方法来做到这一点。 - Doug

2
# 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)

需要使用以下链接器命令-Wl,--start-group * .a -Wl,--end-group包装pjsip库。

这解决了我的问题。


当我将app_module_sip链接到myapp时,CMake似乎会添加所有孙库,例如pjsua 以及 app_module_sip,并且重复的对象会破坏静态初始化,更不用说臃肿的二进制文件大小了。 - nodakai

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接