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)
And I've made sure when looking for the actual libraries that I have the *.a version of them.
Currently the project imports:
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.
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++
Which makes me wonder:
So, could someone please explain to me:
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++")
This works without passing a -static
which creates other big issues, and can essentially mix static and dynamic libraries.
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).
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]
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.