Ich versuche, ein plattformübergreifendes Build-System mit CMake zum Laufen zu bringen. Jetzt hat die Software einige Abhängigkeiten. Ich habe sie selbst kompiliert und auf meinem System installiert.
Einige Beispieldateien, die installiert wurden:
-- Installing: /usr/local/share/SomeLib/SomeDir/somefile
-- Installing: /usr/local/share/SomeLib/SomeDir/someotherfile
-- Installing: /usr/local/lib/SomeLib/somesharedlibrary
-- Installing: /usr/local/lib/SomeLib/cmake/FindSomeLib.cmake
-- Installing: /usr/local/lib/SomeLib/cmake/HelperFile.cmake
Jetzt hat CMake eine, find_package()
die eine Find*.cmake
Datei öffnet und nach der Bibliothek im System sucht und einige Variablen wie SomeLib_FOUND
usw. definiert .
Meine CMakeLists.txt enthält ungefähr Folgendes:
set(CMAKE_MODULE_PATH "/usr/local/lib/SomeLib/cmake/;${CMAKE_MODULE_PATH}")
find_package(SomeLib REQUIRED)
Der erste Befehl definiert, wo CMake nach dem sucht, Find*.cmake
und ich habe das Verzeichnis hinzugefügt, SomeLib
in dem FindSomeLib.cmake
das gefunden werden kann, damit es find_package()
wie erwartet funktioniert.
Dies ist jedoch etwas seltsam, da einer der Gründe dafür darin find_package()
besteht, sich von nicht codierungsübergreifenden, hartcodierten Pfaden zu entfernen.
Wie wird das normalerweise gemacht? Soll ich das cmake/
Verzeichnis von SomeLib
in mein Projekt kopieren und das CMAKE_MODULE_PATH
relativ einstellen ?
Antworten:
Der Befehl
find_package
hat zwei Modi:Module
Modus undConfig
Modus. Sie versuchen, denModule
Modus zu verwenden , wenn Sie denConfig
Modus tatsächlich benötigen .Modulmodus
Find<package>.cmake
Datei in Ihrem Projekt. Etwas wie das:CMakeLists.txt
Inhalt:Beachten Sie, dass dies
CMAKE_MODULE_PATH
eine hohe Priorität hat und nützlich sein kann, wenn Sie eine Standarddatei neu schreiben müssenFind<package>.cmake
.Konfigurationsmodus (installieren)
<package>Config.cmake
Datei befindet sich außerhalb und wird aufinstall
Befehl eines anderen Projekts erstellt (Foo
zum Beispiel).foo
Bibliothek:Vereinfachte Version der Konfigurationsdatei:
Standardmäßig im
CMAKE_INSTALL_PREFIX
Verzeichnis installiertes Projekt :Konfigurationsmodus (verwenden)
Verwenden Sie
find_package(... CONFIG)
diese Option , um dasFooConfig.cmake
importierte Ziel einzuschließenfoo
:Beachten Sie, dass das importierte Ziel in hohem Maße konfigurierbar ist. Siehe meine Antwort .
Aktualisieren
quelle
configure_package_config_file
. Übrigens, wenn Sie weitere Vorschläge haben, können Sie mir eine Pull-Anfrage senden.bin/lib
(versuchen Sie, die ausführbare Datei zu installieren und unter Windows auszuführen). Und Namespaces sehen sehr hübsch aus, also werde ich sie auch behalten :) Außerdem habe ichmonolithic
Build hinzugefügt .Wenn Sie sich selbst
cmake
generierenSomeLib
möchten (z. B. als Teil eines Superbuilds), sollten Sie die Benutzerpaketregistrierung verwenden . Dies erfordert keine fest codierten Pfade und ist plattformübergreifend. Unter Windows (einschließlich mingw64) funktioniert es über die Registrierung. Wenn Sie untersuchen, wie die Liste der Installationspräfixe imCONFIG
Modus des Befehls find_packages () erstellt wird , werden Sie feststellen , dass die Benutzerpaketregistrierung eines der Elemente ist.Kurze Anleitung
Verknüpfen Sie die Ziele
SomeLib
, die Sie außerhalb dieses externen Projekts benötigen, indem Sie sie einem Exportsatz in denCMakeLists.txt
Dateien hinzufügen, in denen sie erstellt werden:Erstellen Sie eine
XXXConfig.cmake
Datei für dieSomeLib
in seinem${CMAKE_CURRENT_BUILD_DIR}
und speichert diese Position im Benutzerpaket Registry , indem Sie zwei Anrufe zu exportieren () auf den imCMakeLists.txt
Zusammenhang mitSomeLib
:find_package(SomeLib REQUIRED)
Geben Sie Ihren Befehl in derCMakeLists.txt
Datei des Projekts aus, die davon abhängt,SomeLib
ohne dass die "plattformübergreifenden fest codierten Pfade" an der Datei bastelnCMAKE_MODULE_PATH
.Wenn es der richtige Ansatz sein könnte
Dieser Ansatz eignet sich wahrscheinlich am besten für Situationen, in denen Sie Ihre Software niemals nach dem Build-Verzeichnis verwenden (z. B. wenn Sie Cross-Compilieren und niemals etwas auf Ihrem Computer installieren oder wenn Sie die Software nur zum Ausführen von Tests erstellen das Build-Verzeichnis), da es einen Link zu einer .cmake-Datei in Ihrer "Build" -Ausgabe erstellt, die vorübergehend sein kann.
Wenn Sie jedoch nie
SomeLib
in Ihrem Workflow installieren ,EXPORT(PACKAGE <name>)
können Sie durch Aufrufen den fest codierten Pfad vermeiden. Und natürlich kennen Sie bei der InstallationSomeLib
wahrscheinlich Ihre PlattformCMAKE_MODULE_PATH
usw., sodass Sie mit der hervorragenden Antwort von @ user2288008 behandelt werden.quelle
Sie nicht brauchen das Modul Pfad per se zu spezifizieren. CMake wird mit einem eigenen Satz integrierter find_package-Skripts ausgeliefert. Der Speicherort befindet sich im Standard-CMAKE_MODULE_PATH.
Der normalere Anwendungsfall für abhängige Projekte, die CMakeified wurden, besteht darin, den Befehl external_project von CMake zu verwenden und dann die Cake-Datei Use [Project] aus dem Unterprojekt einzuschließen. Wenn Sie nur das Skript "Find [Project] .cmake" benötigen, kopieren Sie es aus dem Teilprojekt in den Quellcode Ihres eigenen Projekts, und Sie müssen CMAKE_MODULE_PATH nicht erweitern, um das Teilprojekt auf Systemebene zu finden.
quelle
their location is in the default CMAKE_MODULE_PATH
StandardmäßigCMAKE_MODULE_PATH
ist leerCMAKE_MODULE_PATH
Windows leer.Wenn Sie CMake nicht vertrauen, dass es über dieses Modul verfügt , gehen Sie wie folgt vor: Kopieren Sie das
find_SomeLib.cmake
und seine Abhängigkeiten in Ihrcmake/
Verzeichnis. Das mache ich als Fallback. Es ist jedoch eine hässliche Lösung.Beachten Sie, dass die
FindFoo.cmake
Module jeweils eine Art Brücke zwischen Plattformabhängigkeit und Plattformunabhängigkeit darstellen. Sie suchen an verschiedenen plattformspezifischen Stellen nach Pfaden in Variablen, deren Namen plattformunabhängig sind.quelle