CMake和静态链接

时间:2013-06-07 19:04:51

标签: gcc linker cmake static-libraries static-linking

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

不按特定顺序排列,每个库都有很多错误。

看看海湾合作委员会的最后一行,我看到:

/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 ++似乎是为静态链接设置的,但我仍然会收到错误
  3. 那么,有人可以向我解释一下:

    1. 如何使用CMake
    2. 设置部分静态链接
    3. CMAKE_EXE_LINKER_FLAGS是我唯一需要设置的吗?
    4. 我是否应该强制提到的库的静态链接,而不是整个项目?
    5. 如果问题太多或过于局部化,请原谅我,我之前没有尝试过,而且我似乎无法在网上找到太多信息。

2 个答案:

答案 0 :(得分:28)

我已成功使用以下方法解决了我的问题:

#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的情况下工作,这会产生其他重大问题,并且基本上可以混合使用静态库和动态库。

只要静态库的顺序是正确的,并且只要满足静态库的依赖关系,我就得到一个ELF,它加载动态的东西(即在我的情况下是mysqlclient,libmysql ++)和静态库所有其余的( 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

注意:没有-static-libstdc++

,Poco无法静态链接

我希望这有助于任何人坚持类似的事情。

答案 1 :(得分:15)

如何使用CMake设置静态链接

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

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

find_library(SOMELIB libsomelib.a)

而不是:

find_library(SOMELIB somelib)