45

Ich möchte die Kontrolle über den Typ der Bibliotheken haben, die mit meinen Binärdateien in CMake gefunden/verlinkt werden. Das endgültige Ziel ist es, Binärdateien "so statisch wie möglich" zu erzeugen, das statisch mit jeder Bibliothek verknüpft wird, die eine statische Version hat. Dies ist wichtig, da dies die Portabilität von Binärdateien über verschiedene Systeme hinweg während des Testens ermöglichen würde.CMake: Wie man Binärdateien "so statisch wie möglich" erzeugt

ATM scheint ziemlich schwer zu erreichen, da die FindXXX.cmake-Pakete, oder genauer gesagt, der find_library-Befehl immer die dynamischen Bibliotheken aufnimmt, wenn sowohl statische als auch dynamische verfügbar sind.

Tipps zur Umsetzung dieser Funktionalität - vorzugsweise auf elegante Weise - wären uns sehr willkommen!

+0

Nicht ganz ein Betrüger von: http://stackoverflow.com/questions/2113231/making-cmake-choose-static - Verknüpfung, wenn möglich, die GCC-spezifisch ist. –

+0

Nicht nur, dass es gcc-spezifisch ist, es ist auch eine unpraktische Lösung. Siehe meinen Kommentar zu der anderen Frage. – pszilard

+0

@pszilard Haben Sie schließlich die Lösung gefunden? Ich versuche dasselbe mit g ++ zu machen. – augustin

Antwort

14

Eine gut gemachte FindXXX.cmake-Datei enthält etwas dafür. Wenn Sie in FindBoost.cmake suchen, können Sie die Variable Boost_USE_STATIC_LIBS so einstellen, dass sie steuert, ob statische oder gemeinsam genutzte Bibliotheken gefunden werden. Leider implementiert eine Mehrheit der Pakete dies nicht.

Wenn ein Modul den Befehl find_library verwendet (die meisten tun), können Sie das Verhalten von CMake über die Variable ändern. Hier ist der relevante CMake Code aus FindBoost.cmake diese verwenden:

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) 

Sie können entweder diese setzen, bevor find_package Aufruf, oder besser, können Sie die .cmake modifizieren Dateien selbst und zurück in die Gemeinschaft beitragen.

Für die .cmake-Dateien, die ich in meinem Projekt verwende, behalte ich sie alle in einem eigenen Ordner innerhalb der Quellcodeverwaltung. Ich tat dies, weil ich fand, dass die korrekte .cmake-Datei für einige Bibliotheken inkonsistent war und meine eigene Kopie erlaubte mir, Änderungen vorzunehmen und sicherzustellen, dass jeder, der den Code auscheckte, die gleichen Build-Systemdateien hatte.

+0

Danke für den Kommentar, ich bin tatsächlich zu der Schlussfolgerung in der Zwischenzeit gekommen, dass das oben genannte die einzig mögliche Lösung ist, um die statische Version von externen Bibliotheken zu erkennen. Dies ist jedoch ein ziemlich schmutziger Weg, ich würde es vorziehen, keine Suffixe angeben zu müssen. Leider, basierend auf Diskussionen auf der CMake-Mailing-Liste, scheint es, dass Windows eine ziemlich verwirrende Bibliotheksbenennung hat, es gibt keinen Plan, es richtig zu implementieren. Dies sollte jedoch auf dem meisten * NIX-System funktionieren. – pszilard

+0

Beachten Sie, dass die obigen Befehle nicht die statischen Bibliotheksdateinamen an CMAKE_FIND_LIBRARY_SUFFIXES voranstellen sollten, wenn * nur * die statischen Bibliotheken erkannt werden sollen (und somit möglicherweise die Konfiguration fehlschlägt), sondern stattdessen diese Variable auf diese Dateinamen setzt. *() Funktionen von jemals gegriffenen Bibliotheken mit den üblichen Suffixen – mabraham

+1

Beachten Sie auch, dass es egal ist, wie "gut gemacht" das FindXXXX.cmake-Paket ist, wenn die Bibliothek in einem impliziten Link-Verzeichnis gefunden wird, zB Systempfad. CMake absichtlich kehrt zu -lXXXX zurück, damit der Linker in diesem Fall seine normale Auflösung verwenden kann - siehe http://public.kitware.com/pipermail/cmake/2015-January/059702.html – mabraham

26

Ich habe einige Untersuchungen durchgeführt und obwohl ich keine befriedigende Lösung für das Problem finden konnte, fand ich eine halbe Lösung.

Das Problem der statischen baut läuft darauf hinaus, 3 Dinge auf:

  1. Gebäude und die Verknüpfung des internen Bibliotheken des Projektes.

    Ziemlich einfach, man muss nur den BUILD_SHARED_LIBS Schalter OFF umlegen.

  2. Statische Versionen von externen Bibliotheken finden.

    Die einzige Möglichkeit scheint CMAKE_FIND_LIBRARY_SUFFIXES zu sein, das gewünschte Dateisuffix (es) zu enthalten (es ist eine Prioritätenliste).

    Diese Lösung ist ziemlich "dreckig" und sehr gegen die plattformübergreifenden Bestrebungen von CMake. IMHO sollte dies hinter den Kulissen von CMake gehandhabt werden, aber soweit ich es verstanden habe, scheint es wegen der ".lib" Verwirrung unter Windows, dass die CMake Entwickler die aktuelle Implementierung bevorzugen.

  3. Statisch mit Systembibliotheken verknüpfen.

CMake bietet eine Option LINK_SEARCH_END_STATIC, die auf der Dokumentation basiert: „Ende einer Verbindungsleitung, so dass statische Systembibliotheken verwendet werden." Man würde denken, das ist es, das Problem ist gelöst. Es scheint jedoch, dass die aktuelle Implementierung nicht der Aufgabe gewachsen ist. Wenn die Option aktiviert ist, erzeugt CMake einen impliziten Linker-Aufruf mit einer Argumentliste, die mit endet Die Optionen, die an den Linker übergeben werden, einschließlich -Wl,-Bstatic, reichen jedoch nicht aus. Nur das Anweisen des Linkers, statisch zu verknüpfen, führt zu einem Fehler, in meinem Fall: /usr/bin/ld: cannot find -lgcc_s. Was fehlt, ist auch gcc mitzuteilen, dass wir statische Verknüpfungen durch die -static Argument, das nicht erzeugen an den Linker Aufruf von CMake ist. ich denke, dass dies ein Fehler ist, aber ich habe keine Bestätigung bekommen von den Entwicklern noch verwaltet.

Schließlich ich denke, all dies könnte und sollte von CMake hinter den Kulissen erledigt werden, Schließlich ist es nicht so kompliziert, außer dass es unter Windows unmöglich ist - wenn das als kompliziert gilt ...

+1

Sollten Sie 'BUILD_SHARED_LIBS' nicht auf off setzen? (so dass es keine Shared Libraries erstellen würde?) – Nooble

+0

Haha, in fast fünf Jahren bist du der Erste, der diesen Fehler bemerkt. – pszilard