45

Je voudrais avoir le contrôle sur le type des bibliothèques qui sont trouvées/liées avec mes binaires dans CMake. Le but final est de générer des binaires "aussi statiques que possible" qui soit lié statiquement à toutes les bibliothèques qui ont une version statique disponible. Ceci est important car cela permettrait la portabilité des binaires sur différents systèmes pendant les tests.CMake: comment produire des binaires "aussi statiques que possible"

ATM cela semble être assez difficile à réaliser car les paquets FindXXX.cmake, ou plus précisément la commande find_library, récupère toujours les bibliothèques dynamiques quand les deux statiques et dynamiques sont disponibles.

Des conseils sur la façon d'implémenter cette fonctionnalité - de préférence de manière élégante - seraient les bienvenus!

+0

Pas du dupe de: http://stackoverflow.com/questions/2113231/making-cmake-choose-static -linkage-when-possible, qui est spécifique à GCC. –

+0

En fait, non seulement c'est gcc spécifique, mais c'est aussi une solution peu pratique. Voir mon commentaire à l'autre question. – pszilard

+0

@pszilard Avez-vous fini par trouver la solution? J'essaye de faire la même chose avec g ++. – augustin

Répondre

14

Un fichier FindXXX.cmake bien fait contiendra quelque chose pour cela. Si vous regardez dans FindBoost.cmake, vous pouvez définir la variable Boost_USE_STATIC_LIBS pour contrôler si elle trouve ou non des bibliothèques statiques ou partagées. Malheureusement, une majorité de paquets ne l'implémente pas.

Si un module utilise la commande find_library (la plupart le font), vous pouvez modifier le comportement de CMake via la variable CMAKE_FIND_LIBRARY_SUFFIXES. Voici le code CMake pertinent de FindBoost.cmake à utiliser:

IF(WIN32) 
    SET(CMAKE_FIND_LIBRARY_SUFFIXES .lib .a ${CMAKE_FIND_LIBRARY_SUFFIXES}) 
ELSE(WIN32) 
    SET(CMAKE_FIND_LIBRARY_SUFFIXES .a ${CMAKE_FIND_LIBRARY_SUFFIXES}) 
ENDIF(WIN32) 

Vous pouvez mettre cela avant d'appeler find_package, ou, mieux, vous pouvez modifier les .cmake fichiers eux-mêmes et de contribuer à la communauté.

Pour les fichiers .cmake que j'utilise dans mon projet, je les garde tous dans leur propre dossier dans le contrôle des sources. J'ai fait cela parce que j'ai trouvé qu'avoir le bon fichier .cmake pour certaines bibliothèques était incohérent et garder ma propre copie m'a permis d'apporter des modifications et de s'assurer que tous ceux qui ont extrait le code auraient les mêmes fichiers système.

+0

Merci pour le commentaire, je suis effectivement venu à la conclusion en attendant que ce qui précède est la seule solution possible pour obtenir la version statique des bibliothèques externes détectés. Cependant, c'est une manière assez sale, je préférerais ne pas devoir spécifier des suffixes. Malheureusement, d'après les discussions sur la liste de diffusion CMake, il semble que Windows ayant une dénomination de bibliothèque assez confuse, il n'est pas prévu de l'implémenter correctement. Cela devrait fonctionner sur la plupart des systèmes * NIX, cependant. – pszilard

+0

Notez que si vous voulez que seules les bibliothèques statiques soient détectées (et donc que la configuration échoue, les commandes ci-dessus ne doivent pas ajouter les noms de fichiers de la bibliothèque statique à CMAKE_FIND_LIBRARY_SUFFIXES, mais plutôt définir cette variable sur ces noms de fichiers. *() fonctions de jamais ramasser des bibliothèques partagées avec les suffixes habituels – mabraham

+1

Notez également que peu importe comment "bien fait" le paquet FindXXXX.cmake est si la bibliothèque est trouvée dans un répertoire de lien implicite, par exemple le chemin du système. retourne à -lXXXX pour permettre au lieur d'utiliser sa résolution normale dans ce cas - voir http://public.kitware.com/pipermail/cmake/2015-January/059702.html – mabraham

26

J'ai fait quelques recherches et même si je n'ai pas trouvé de solution satisfaisante au problème, j'ai trouvé une demi-solution.

Le problème de statique se résume à 3 choses:

  1. du bâtiment et de relier les bibliothèques internes du projet. Assez simple, il suffit de retourner le commutateur BUILD_SHARED_LIBSOFF.

  2. Recherche de versions statiques de bibliothèques externes.

    La seule manière semble être de définir CMAKE_FIND_LIBRARY_SUFFIXES pour contenir le (s) suffixe (s) de fichier souhaité (s) (c'est une liste de priorité).

    Cette solution est assez "sale" et très contraire aux ambitions croisées de CMake. À mon humble avis cela devrait être manipulé dans les coulisses par CMake, mais autant que j'ai compris, à cause de la confusion ".lib" sur Windows, il semble que les développeurs CMake préfèrent l'implémentation actuelle.

  3. Liaison statique aux bibliothèques système.

CMake fournit une option qui LINK_SEARCH_END_STATIC basée sur la documentation: « Mettre fin à une ligne de liaison tels que les bibliothèques système statiques sont utilisés." On pourrait penser que le problème est résolu, mais il semblerait que l'implémentation actuelle ne soit pas à la hauteur de la tâche.Si l'option est activée, CMake génère un appel de linker implicite avec une liste d'arguments qui se termine par les options passées à l'éditeur de liens, y compris -Wl,-Bstatic, mais cela ne suffit pas, mais indiquer à l'éditeur de liens un lien statique génère une erreur, dans mon cas: /usr/bin/ld: cannot find -lgcc_s. Il manque également à gcc d'avoir besoin d'une liaison statique via -static argument qui est pas généré à l'appel de linker par CMake. Je pense que c'est un bug, mais je n'ai pas réussi à obtenir

une confirmation des développeurs encore. Enfin, je pense que tout cela pourrait et devrait être fait par CMake dans les coulisses, après tout, ce n'est pas si compliqué, sauf que c'est impossible sur Windows - si ça compte comme compliqué ...

+1

Ne devriez-vous pas mettre 'BUILD_SHARED_LIBS' à off (donc ça * ne construirait pas de librairies partagées)? – Nooble

+0

Hahha, en presque cinq ans tu es le premier à noter cette erreur. – pszilard

Questions connexes