CMake和静态链接

z6psavjg  于 2022-11-24  发布在  其他
关注(0)|答案(3)|浏览(258)

我在一个项目中使用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标志?好像它们被跳过/排除在静态链接之外。

  1. mysqlclient、mysqlpp和crypto++似乎是为静态链接设置的,但我仍然收到错误
    那么,可否有人向我解释一下:
    1.如何使用CMake设置部分静态链接
  2. CMAKE_EXE_LINKER_FLAGS是唯一需要设置的吗?
    1.我是否应该为所提到的库而不是整个项目强制静态链接?
    请原谅我,如果这些是太多或太本地化的问题,我还没有尝试过这个之前,我似乎不能找到太多的信息在网上。
bmvo0sr5

bmvo0sr51#

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

#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-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库的情况下,它只得到了库的完整路径和名称,而不是标志,-Bdynamic只能通过使用上面的行来关闭。
注意:如果没有-static-libstdc++,则无法静态链接Poco
我希望这能帮助任何陷入类似困境的人。

ubby3x7f

ubby3x7f2#

如何使用CMake设置静态链接

嗯......你不知道:)CMake不是这样工作的:在CMake中,首先找到库的绝对路径,然后使用target_link_libraries链接到该库。
因此,如果要链接到静态库,则需要搜索该静态库:

find_library(SOMELIB libsomelib.a)

而不是:

find_library(SOMELIB somelib)
u5rb5r59

u5rb5r593#

对于cmake的最新版本,如果您指定.a文件的完整文件名,那么将lib链接为静态就足够聪明了。

TARGET_LINK_LIBRARIES(pfs ... liburing.a  ...)

它将生成编译器cmd行:

ld ... -Wl,-Bstatic -luring -Wl,-Bdynamic ...

而cmd行的语法是GCC的语法,用于链接静态库。https://stackoverflow.com/a/4500201/388354

相关问题