Wie kopiere ich DLL-Dateien mit CMake in denselben Ordner wie die ausführbare Datei?
98
Wir verwenden CMake zum Generieren der Visual Studio-Dateien unserer Quellen in unserem SVN. Jetzt erfordert mein Tool, dass sich einige DLL-Dateien im selben Ordner wie die ausführbare Datei befinden. Die DLL-Dateien befinden sich in einem Ordner neben der Quelle.
Wie kann ich meine CMakeLists.txtso ändern , dass das generierte Visual Studio-Projekt entweder bereits die bestimmten DLL-Dateien in den Release- / Debug-Ordnern enthält oder diese beim Kompilieren kopiert?
Wenn Sie je nach Konfiguration unterschiedliche DLLs kopieren müssen (Release, Debug, z. B.), können Sie diese in Unterverzeichnissen mit der entsprechenden Konfiguration haben:, /libs/Releaseund /libs/Debug. Anschließend müssen Sie den Konfigurationstyp add_custom_commandwie folgt in den Pfad zur DLL des Aufrufs einfügen :
Kurzer Hinweis zu dem, was in meinem Fall funktioniert hat, falls es in Zukunft jemand anderem hilft: Ich habe ein statisches Bibliotheksprojekt, mit dem die ausführbare Hauptdatei optional verknüpft ist, und für diese Bibliothek muss beim Hinzufügen eine DLL kopiert werden. Also in der CMakeLists.txt-Datei dieser Bibliothek, die ich ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/$<CONFIG>für das Ziel verwendet habe. Andernfalls würde es in den Bibliothekserstellungspfad kopiert, was nutzlos war.
AberrantWolf
Ist es nicht das Ziel der cmake- install()Direktiven, die Binärdateien zusammenzustellen? Oder vielleicht LIBRARYDinge machen? Ich kenne die Toolchain nicht wirklich.
Sandburg
1
$<TARGET_FILE_DIR:MyTest>- Was ist es? Wie man Infos druckt, was genau das bedeutet
ilw
Sofern ich bei der Integration des Befehls nichts verpasst habe, funktioniert diese Methode nicht für Bibliotheken, die mit hinzugefügt wurden IMPORTED_LIBRARIES. Es wird beanstandet, dass ein Post-Build-Befehl nicht ausgeführt werden kann, wenn nichts erstellt wurde.
Tzalumen
2
Beim Testen und Stoßen meines cmake: Wenn Sie IMPORTEDBibliotheken verwenden und die DLLs verschieben müssen, müssen Sie einen varianten Befehl verwenden. Wenn Sie Ihre IMPORTEDBibliothek so hinzugefügt haben, wie MyImportedLibSie es verwenden würden COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:MyImportedLib> $<TARGET_FILE_DIR:MyTest>Beachten Sie, dass Sie zum Ausführen mehrerer Post-Build-Befehle alle in einen benutzerdefinierten Befehl add_custom_command(TARGET MyTest POST_BUILD COMMAND #your first command# COMMAND #Your second command#)
eingebunden haben müssen,
24
Ich habe diese Zeilen in meine CMakeLists.txt-Datei der obersten Ebene eingefügt. Alle von CMake kompilierten Bibliotheken und ausführbaren Dateien werden in der obersten Ebene des Build-Verzeichnisses abgelegt, damit die ausführbaren Dateien die Bibliotheken finden können und es einfach ist, alles auszuführen.
set (CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
set (CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
Beachten Sie, dass dies das Problem des OP beim Kopieren vorkompilierter Binärdateien aus dem Quellverzeichnis des Projekts nicht löst.
Ich hatte heute dieses Problem, als ich versuchte, ein Windows-Build meines Programms zu erstellen. Und am Ende habe ich selbst recherchiert, da mich all diese Antworten nicht zufriedenstellten. Es gab drei Hauptprobleme:
Ich wollte, dass Debug-Builds mit Debug-Versionen von Bibliotheken verknüpft werden und Release-Builds mit Release-Builds von Bibliotheken verknüpft werden.
Außerdem wollte ich, dass korrekte Versionen von DLL-Dateien (Debug / Release) in Ausgabeverzeichnisse kopiert werden.
Und ich wollte all dies erreichen, ohne komplexe und fragile Skripte zu schreiben.
Nach dem Durchsuchen einiger CMake-Handbücher und einiger Multiplattform-Projekte bei github habe ich folgende Lösung gefunden:
Deklarieren Sie Ihre Bibliothek als Ziel mit dem Attribut "IMPORTED", verweisen Sie auf das Debugging und geben Sie die .lib- und .dll-Dateien frei.
Verknüpfen Sie dieses Ziel wie gewohnt mit Ihrem Projekt
target_link_libraries(YourProg sdl2 ...)
Führen Sie einen benutzerdefinierten Build-Schritt aus, um die DLL-Datei an ihr Ziel zu kopieren, wenn sie seit dem vorherigen Build irgendwie geändert wurde
Ein Nachtrag zur akzeptierten Antwort, der als separate Antwort hinzugefügt wurde, damit ich die Code-Formatierung erhalte:
Wenn Sie Ihre DLLs im selben Projekt erstellen, befinden sie sich normalerweise in den Verzeichnissen Release, Debug usw. Sie müssen die Visual Studio-Umgebungsvariablen verwenden, um sie korrekt zu kopieren. z.B:
Sie können die Variable CMake CMAKE_BUILD_TYPE nicht für die Konfiguration verwenden, da sie zur Zeit der VS-Projektgenerierung aufgelöst wird und immer die Standardeinstellung ist.
SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY
${PROJECT_SOURCE_DIR}/lib CACHE
PATH "Directory where all the .lib files are dumped." FORCE)
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY
${PROJECT_SOURCE_DIR}/bin CACHE
PATH "Directory where .exe and .dll files are dumped." FORCE)
Ich bin ein CMake-Anfänger, aber ich wollte trotzdem meine Erfahrungen teilen. In meinem Fall benötigte ich eine Kopie nach der Installation, damit alle meine Binärdateien gespeichert sind. Im Fall von Binärdateien von Drittanbietern, die in CMake importiert werden können, funktioniert Folgendes für mich:
find_package( dependency REQUIRED )
if( MSVC )
# If done properly and if the dependency has a correct config file, IMPORTED_LOCATION_RELEASE should be defined
get_target_property( DEP_SHARED_LIB_PATH dependency IMPORTED_LOCATION_RELEASE )
# Create a bin directory in the install folder
add_custom_command(TARGET BGS POST_BUILD COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_INSTALL_PREFIX}/bin/)
# Copy the shared lib file
add_custom_command(TARGET BGS POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${DEP_SHARED_LIB_PATH} ${CMAKE_INSTALL_PREFIX}/bin/)
endif()
Offensichtlich kann IMPORTED_LOCATION_RELEASE Varianten haben, abhängig davon, wie die gemeinsam genutzte Bibliothek erstellt / installiert wurde. Könnte IMPORTED_LOCATION_DEBUG sein.
Vielleicht gibt es einen besseren Weg, um diesen Eigenschaftsnamen zu erhalten, ich weiß es nicht.
Verschieben von Dateien während der Erstellung mit install
Ich hatte dieses Problem beim Versuch, dem offiziellen CMake-Tutorial zu Schritt 9 zu folgen . Dies war der Speicherort der Datei, die ich verschieben wollte:
src
|_build
|_Debug
- `MathFunctions.dll`
Dies war der Speicherort, an dem sich die Datei befinden sollte:
src
|_build
|_install
|_bin
- `MathFunctions.dll`
Da diese DLL als gemeinsam genutzte Bibliothek generiert wurde, habe ich diese Zeile nur CMakeLists.txtin das Unterverzeichnis aufgenommen , das den Quellcode für die Bibliothek enthieltsrc/Mathfunctions/CMakeLists.txt
Dank Ihrer Antworten konnte ich darüber nachdenken. Ist nur eine Zeile, also denke ich ist ok. Das $<CONFIG>kann zwei Werte haben: Debuggen oder Freigeben Je nachdem, wie das Projekt erstellt wurde, ist die ursprüngliche Frage erforderlich.
${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/$<CONFIG>
für das Ziel verwendet habe. Andernfalls würde es in den Bibliothekserstellungspfad kopiert, was nutzlos war.install()
Direktiven, die Binärdateien zusammenzustellen? Oder vielleichtLIBRARY
Dinge machen? Ich kenne die Toolchain nicht wirklich.$<TARGET_FILE_DIR:MyTest>
- Was ist es? Wie man Infos druckt, was genau das bedeutetIMPORTED_LIBRARIES
. Es wird beanstandet, dass ein Post-Build-Befehl nicht ausgeführt werden kann, wenn nichts erstellt wurde.IMPORTED
Bibliotheken verwenden und die DLLs verschieben müssen, müssen Sie einen varianten Befehl verwenden. Wenn Sie IhreIMPORTED
Bibliothek so hinzugefügt haben, wieMyImportedLib
Sie es verwenden würdenCOMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:MyImportedLib> $<TARGET_FILE_DIR:MyTest>
Beachten Sie, dass Sie zum Ausführen mehrerer Post-Build-Befehle alle in einen benutzerdefinierten Befehladd_custom_command(TARGET MyTest POST_BUILD COMMAND #your first command# COMMAND #Your second command#)
Ich habe diese Zeilen in meine CMakeLists.txt-Datei der obersten Ebene eingefügt. Alle von CMake kompilierten Bibliotheken und ausführbaren Dateien werden in der obersten Ebene des Build-Verzeichnisses abgelegt, damit die ausführbaren Dateien die Bibliotheken finden können und es einfach ist, alles auszuführen.
Beachten Sie, dass dies das Problem des OP beim Kopieren vorkompilierter Binärdateien aus dem Quellverzeichnis des Projekts nicht löst.
quelle
Ich hatte heute dieses Problem, als ich versuchte, ein Windows-Build meines Programms zu erstellen. Und am Ende habe ich selbst recherchiert, da mich all diese Antworten nicht zufriedenstellten. Es gab drei Hauptprobleme:
Ich wollte, dass Debug-Builds mit Debug-Versionen von Bibliotheken verknüpft werden und Release-Builds mit Release-Builds von Bibliotheken verknüpft werden.
Außerdem wollte ich, dass korrekte Versionen von DLL-Dateien (Debug / Release) in Ausgabeverzeichnisse kopiert werden.
Und ich wollte all dies erreichen, ohne komplexe und fragile Skripte zu schreiben.
Nach dem Durchsuchen einiger CMake-Handbücher und einiger Multiplattform-Projekte bei github habe ich folgende Lösung gefunden:
Deklarieren Sie Ihre Bibliothek als Ziel mit dem Attribut "IMPORTED", verweisen Sie auf das Debugging und geben Sie die .lib- und .dll-Dateien frei.
Verknüpfen Sie dieses Ziel wie gewohnt mit Ihrem Projekt
Führen Sie einen benutzerdefinierten Build-Schritt aus, um die DLL-Datei an ihr Ziel zu kopieren, wenn sie seit dem vorherigen Build irgendwie geändert wurde
quelle
Ein Nachtrag zur akzeptierten Antwort, der als separate Antwort hinzugefügt wurde, damit ich die Code-Formatierung erhalte:
Wenn Sie Ihre DLLs im selben Projekt erstellen, befinden sie sich normalerweise in den Verzeichnissen Release, Debug usw. Sie müssen die Visual Studio-Umgebungsvariablen verwenden, um sie korrekt zu kopieren. z.B:
für die Quelle und
für das Ziel. Beachten Sie die Flucht!
Sie können die Variable CMake CMAKE_BUILD_TYPE nicht für die Konfiguration verwenden, da sie zur Zeit der VS-Projektgenerierung aufgelöst wird und immer die Standardeinstellung ist.
quelle
$<CONFIGURATION>
Sie können auch den Befehl find_library verwenden:
Mit einem definierten EXECUTABLE_PATH zum Beispiel:
Sie können die DLL-Dateien, die Ihre ausführbare Datei benötigt, mit verschieben
quelle
Dies ist für einen von ihnen nützlich
quelle
Sie müssen wahrscheinlich ein benutzerdefiniertes Ziel hinzufügen und es von einem Ihrer ausführbaren Ziele abhängig machen.
Um eine Datei mit der obigen Funktion zu kopieren, verwenden Sie:
quelle
Ich bin ein CMake-Anfänger, aber ich wollte trotzdem meine Erfahrungen teilen. In meinem Fall benötigte ich eine Kopie nach der Installation, damit alle meine Binärdateien gespeichert sind. Im Fall von Binärdateien von Drittanbietern, die in CMake importiert werden können, funktioniert Folgendes für mich:
Offensichtlich kann IMPORTED_LOCATION_RELEASE Varianten haben, abhängig davon, wie die gemeinsam genutzte Bibliothek erstellt / installiert wurde. Könnte IMPORTED_LOCATION_DEBUG sein.
Vielleicht gibt es einen besseren Weg, um diesen Eigenschaftsnamen zu erhalten, ich weiß es nicht.
quelle
Verschieben von Dateien während der Erstellung mit
install
Ich hatte dieses Problem beim Versuch, dem offiziellen CMake-Tutorial zu Schritt 9 zu folgen . Dies war der Speicherort der Datei, die ich verschieben wollte:
Dies war der Speicherort, an dem sich die Datei befinden sollte:
Da diese DLL als gemeinsam genutzte Bibliothek generiert wurde, habe ich diese Zeile nur
CMakeLists.txt
in das Unterverzeichnis aufgenommen , das den Quellcode für die Bibliothek enthieltsrc/Mathfunctions/CMakeLists.txt
Dank Ihrer Antworten konnte ich darüber nachdenken. Ist nur eine Zeile, also denke ich ist ok. Das
$<CONFIG>
kann zwei Werte haben: Debuggen oder Freigeben Je nachdem, wie das Projekt erstellt wurde, ist die ursprüngliche Frage erforderlich.quelle