J'utilise CMake dans un projet et j'essaie de lier statiquement certaines bibliothèques. J'ai réglé:
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)
Et je me suis assuré lors de la recherche des bibliothèques réelles que j'en ai la version * .a.
Actuellement, le projet importe:
libPocoNet.a
libPocoUtil.a
libPocoXML.a
libPocoFoundation.a
libmysqlclient.a
libmysqlpp.a
libcrypto++.a
CUDA
Toutes les bibliothèques sont trouvées, et lorsque vous effectuez une liaison dynamique/partagée, elles fonctionnent correctement. J'ai également essayé de définir des drapeaux de compilation:
set(GCC_CXX_FLAGS ${GCC_CXX_FLAGS} "-static-libgcc -static-libstdc++ -static")
Mais en vain. Bien que je n'obtienne aucun problème lors de la compilation, la liaison génère de nombreuses erreurs référence non définie pour les appels trouvés dans les bibliothèques ci-dessus, à savoir:
undefined reference to `mysql_thread_init'
undefined reference to `mysql_real_query'
undefined reference to `pthread_mutex_unlock'
undefined reference to `Poco::ErrorHandler::handle()'
Pas dans cet ordre particulier, et de nombreuses erreurs pour chaque bibliothèque.
En regardant la dernière ligne de GCC, je vois:
/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++
Ce qui me fait me demander:
Alors, quelqu'un pourrait-il m'expliquer:
Veuillez m'excuser s'il s'agit de questions trop nombreuses ou trop localisées, je n'ai jamais essayé cela auparavant et je n'arrive pas à trouver beaucoup d'informations sur le net.
J'ai réussi à résoudre mon problème en utilisant ce qui suit:
#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++")
Cela fonctionne sans passer un -static
ce qui crée d'autres gros problèmes, et peut essentiellement mélanger des bibliothèques statiques et dynamiques.
Tant que l'ordre des bibliothèques statiques est correct, et tant que les dépendances des bibliothèques statiques sont satisfaites, j'obtiens un ELF qui charge ce qui est dynamique (c'est-à-dire dans mon cas mysqlclient, libmysql ++) et statique tout le reste (crypto ++, PocoNet , PocoUtil, PocoXML, PocoFoundation).
Gardez à l'esprit que les bibliothèques liées statiques ont leurs propres dépendances. En examinant mon application de débogage à l'aide de l'application readelf -d, je vois:
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]
Je sais que pthread est importé par Poco :: Runnable, libm est pour les opérations mathématiques, etc. Je ne sais toujours pas si c'est la bonne façon d'utiliser CMake pour la liaison statique partielle.
Dans le cas des bibliothèques packagées Debian, telles que crypto ++, mysql ++, mysqlclient, trouver simplement la bibliothèque * .a a fonctionné, mais dans le cas des bibliothèques Poco, qui ne m'ont obtenu que le chemin d'accès complet et le nom de la bibliothèque, mais pas un indicateur, -Bdynamic
n'a pu être désactivé qu'en utilisant les lignes ci-dessus.
Remarque: Poco n'a pas pu être lié statiquement, sans -static-libstdc++
J'espère que cela aide toute personne coincée à quelque chose de similaire.
Comment configurer la liaison statique à l'aide de CMake
Eh bien ... vous ne le faites pas :) Ce n'est pas ainsi que CMake fonctionne: dans CMake, vous trouvez d'abord le chemin absolu d'une bibliothèque, puis vous y liez avec target_link_libraries.
Donc, si vous souhaitez créer un lien vers une bibliothèque statique, vous devez rechercher cette bibliothèque statique:
find_library(SOMELIB libsomelib.a)
au lieu de:
find_library(SOMELIB somelib)