CMake 和静态链接 [英] CMake and Static Linking

查看:91
本文介绍了CMake 和静态链接的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在一个项目中使用 CMake,并且我正在尝试静态链接一些库.我已经设置:

I'm using CMake in a project, and I'm trying to statically link some libraries. I've set:

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 版本.

And I've made sure when looking for the actual libraries that I have the *.a version of them.

当前项目导入:

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

找到所有库,并且在进行动态/共享链接时,它们工作正常.我也试过设置编译标志:

All libraries are found, and when doing a dynamic/shared linkage, they work fine. I have also tried to set compilation flags:

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

但无济于事.虽然我在编译时没有遇到任何问题,但对于在上述库中找到的调用,链接会抛出很多 未定义引用 错误,即:

But to no avail. While I get no issues while compiling, linkage is throwing alot of undefined reference errors for calls found in the above libraries, i.e:

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

不是按照那个特定的顺序,每个库都有很多错误.

Not in that particular order, and numerous errors for each library.

看 GCC 的最后一行我看到了:

Looking at the last line of GCC I see:

/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++ 似乎设置为静态链接,但我仍然遇到错误

那么,有人可以向我解释一下吗:

So, could someone please explain to me:

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

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

Please excuse me if those are too many or too localized questions, I haven't tried this before, and I can't seem to find much info on the net.

推荐答案

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

I've managed to solve my problem by using the following:

#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 即可工作,并且基本上可以混合静态和动态库.

This works without passing a -static which creates other big issues, and can essentially mix static and dynamic libraries.

只要静态库的顺序是正确的,并且只要静态库的依赖满足,我使用一些动态库(即在我的例子中是mysqlclient,libmysql++)得到一个ELF,其余的都是静态库(crypto++、PocoNet、PocoUtil、PocoXML、PocoFoundation).

As long as the order of static libraries is correct, and as long as dependencies of static libraries are satisfied, I get an ELF using some dynamic libraries (i.e. in my case mysqlclient, libmysql++) and the rest are all static libraries (crypto++, PocoNet, PocoUtil, PocoXML, PocoFoundation).

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

Bear in mind that static linked libraries have their own dependencies. Examining my debug application using readelf -d app, I see:

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 进行部分静态链接的正确方法.

I know that pthread is imported by Poco::Runnable, libm is for math operations, etc. I am still unaware if this is the right way to use CMake for partial static linking.

对于 Debian 打包库,例如 crypto++、mysql++、mysqlclient,只需找到 *.a 库就可以了,但是对于 Poco 库,它只为我提供了库的完整路径和名称,但没有一个标志,-Bdynamic 只能通过使用以上几行来关闭.

In the case of Debian packaged libraries, such as crypto++, mysql++, mysqlclient, simply finding the *.a library worked, but in case of Poco Libraries, which only got me the full path and name of the library, but not a flag, -Bdynamic could only be turned off by using the above lines.

注意:Poco 不能静态链接,没有 -static-libstdc++

Note: Poco could not be linked statically, without -static-libstdc++

我希望这能帮助任何陷入类似问题的人.

I hope this helps anyone stuck at something similar.

这篇关于CMake 和静态链接的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆