35

我在一个项目中使用 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 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++

这让我想知道:

  1. 为什么 Poco 库链接为 -rdynamic,并且没有 -Wl -Bstatic 标志?好像它们被从静态链接中跳过/排除。
  2. mysqlclient、mysqlpp 和 crypto++ 似乎设置为静态链接,但我仍然收到错误

所以,有人可以向我解释一下:

  1. 如何使用 CMake 设置部分静态链接
  2. CMAKE_EXE_LINKER_FLAGS 是我唯一需要设置的吗?
  3. 我应该为提到的库而不是整个项目强制静态链接吗?

如果这些问题太多或太本地化,请原谅,我以前没有尝试过,而且我似乎在网上找不到太多信息。

4

2 回答 2

37

我已经设法通过使用以下方法解决了我的问题:

#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++")

这可以在不通过 a 的情况下工作,-static这会产生其他大问题,并且基本上可以混合静态库和动态库。

只要静态库的顺序正确,并且只要满足静态库的依赖关系,我就可以使用一些动态库(即在我的情况下为mysqlclient,libmysql++)得到一个ELF,其余的都是静态库(crypto++,PocoNet ,PocoUtil,PocoXML,PocoFoundation)。

请记住,静态链接库有自己的依赖项。使用 检查我的调试应用程序readelf -d app,我看到:

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++

我希望这可以帮助任何陷入类似问题的人。

于 2013-06-10T21:04:35.490 回答
23

如何使用 CMake 设置静态链接

嗯......你没有:) 这不是 CMake 的工作方式:在 CMake 中,你首先找到一个库的绝对路径,然后使用 target_link_libraries 链接到它。

因此,如果要链接到静态库,则需要搜索该静态库:

find_library(SOMELIB libsomelib.a)

代替:

find_library(SOMELIB somelib)
于 2013-06-07T21:27:46.270 回答