CMake和静态链接

Æle*_*lex 28 linker gcc 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)
Run Code Online (Sandbox Code Playgroud)

我确定在寻找具有*.a版本的实际库时.

目前该项目进口:

libPocoNet.a 
libPocoUtil.a 
libPocoXML.a 
libPocoFoundation.a 
libmysqlclient.a 
libmysqlpp.a 
libcrypto++.a 
CUDA
Run Code Online (Sandbox Code Playgroud)

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

set(GCC_CXX_FLAGS ${GCC_CXX_FLAGS} "-static-libgcc -static-libstdc++ -static")
Run Code Online (Sandbox Code Playgroud)

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

undefined reference to `mysql_thread_init'
undefined reference to `mysql_real_query'
undefined reference to `pthread_mutex_unlock'
undefined reference to `Poco::ErrorHandler::handle()'
Run Code Online (Sandbox Code Playgroud)

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

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

/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++
Run Code Online (Sandbox Code Playgroud)

这让我想知道:

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

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

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

如果那些问题太多或过于局部化,请原谅我,我之前没有尝试过,而且我似乎无法在网上找到太多信息.

Æle*_*lex 29

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

#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++")
Run Code Online (Sandbox Code Playgroud)

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

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

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]
Run Code Online (Sandbox Code Playgroud)

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.

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.

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

I hope this helps anyone stuck at something similar.


Gui*_*ume 16

如何使用CMake设置静态链接

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

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

find_library(SOMELIB libsomelib.a)
Run Code Online (Sandbox Code Playgroud)

代替:

find_library(SOMELIB somelib)
Run Code Online (Sandbox Code Playgroud)

  • 它可能是库命令的问题,尝试将`-lmysqlclient -lmysqlpp`移动到链接器的开头,看看它是否有所改进. (3认同)