Вопрос по cmake, dll – Как скопировать файлы DLL в ту же папку, что и исполняемый файл с помощью CMake?

81

Мы используем CMake для генерации файлов Visual Studio наших источников в нашем SVN. Теперь мой инструмент требует, чтобы некоторые DLL-файлы находились в той же папке, что и исполняемый файл. Файлы DLL находятся в папке рядом с источником.

Как я могу изменить свойCMakeLists.txt такой, что сгенерированный проект Visual Studio будет уже иметь определенные DLL-файлы в папках выпуска / отладки или скопирует их после компиляции?

Ваш Ответ

6   ответов
13

иблиотеки и исполняемые файлы, скомпилированные CMake, будут помещены в верхний уровень каталога сборки, чтобы исполняемые файлы могли находить библиотеки, и все было легко запустить.

set (CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
set (CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})

Следует отметить, что это не решает проблему OP, заключающуюся в копировании предварительно скомпилированных двоичных файлов из исходного каталога проекта.

2

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)
1

добавить пользовательскую цель и сделайте так, чтобы это зависело от одной из ваших исполняемых целей. Чтобы скопировать файл, используя функцию выше, используйте

COMMAND ${CMAKE_PROGRAM} -E copy_if_different ${CMAKE_BINARY_DIR}/path/to/file.dll ${CMAKE_BINARY_DIR}/where/to/put/file.dll.

-1

find_library(<some_var> NAMES <name_of_lib> PATHS "<path/to/lib>")

С определенным EXECUTABLE_PATH, например:

set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)

Вы можете переместить .dll файлы, которые нужны вашему исполняемому файлу, с помощью

file(COPY ${<some_var>}
    DESTINATION ${EXECUTABLE_OUTPUT_PATH})
5

добавленное как отдельный ответ, чтобы я получил форматирование кода:

Если вы собираете свои библиотеки в одном и том же проекте, они обычно находятся в каталогах Release, Debug и т. Д. Вам придется использовать переменные среды Visual Studio, чтобы правильно их скопировать. например.:

"${PROJECT_BINARY_DIR}/your_library/\$\(Configuration\)/your_library.dll"

для источника и

"${CMAKE_CURRENT_BINARY_DIR}/\$\(Configuration\)/your_library.dll"

для назначения. Обратите внимание на побег!

Вы не можете использовать переменную CMake CMAKE_BUILD_TYPE для конфигурации, поскольку она разрешена во время генерации проекта VS и всегда будет такой, какой она является по умолчанию.

Последняя часть принятого ответа обращается к этому более чистым способом CMake, используя$<CONFIGURATION>
101

Я используюadd_custom_command достичь этого вместе сcmake -E copy_if_different..., Для полной информации бегите

cmake --help-command add_custom_command
cmake -E


Так что в вашем случае, если у вас есть следующая структура каталогов:

/CMakeLists.txt
/src
/libs/test.dll

и ваша цель CMake, к которой применяется командаMyTest, затем вы можете добавить следующее в ваш CMakeLists.txt:

add_custom_command(TARGET MyTest POST_BUILD        # Adds a post-build event to MyTest
    COMMAND ${CMAKE_COMMAND} -E copy_if_different  # which executes "cmake - E copy_if_different..."
        "${PROJECT_SOURCE_DIR}/libs/test.dll"      # <--this is in-file
        
add_custom_command(TARGET MyTest POST_BUILD        # Adds a post-build event to MyTest
    COMMAND ${CMAKE_COMMAND} -E copy_if_different  # which executes "cmake - E copy_if_different..."
        "${PROJECT_SOURCE_DIR}/libs/test.dll"      # <--this is in-file
        $<TARGET_FILE_DIR:MyTest>)                 # <--this is out-file path
lt;TARGET_FILE_DIR:MyTest>) # <--this is out-file path


Если вы просто хотите, чтобы все содержимое/libs/ каталог скопирован, используйтеcmake -E copy_directory:

add_custom_command(TARGET MyTest POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E copy_directory
        "${PROJECT_SOURCE_DIR}/libs"
        
add_custom_command(TARGET MyTest POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E copy_directory
        "${PROJECT_SOURCE_DIR}/libs"
        $<TARGET_FILE_DIR:MyTest>)
lt;TARGET_FILE_DIR:MyTest>)


Если вам нужно скопировать разные dll в зависимости от конфигурации (Release, Debug и т. Д.), Вы можете получить их в подкаталогах с соответствующей конфигурацией:/libs/Release, а также/libs/Debug, Затем вам нужно ввести тип конфигурации в путь к DLL вadd_custom_command звоните, вот так:

add_custom_command(TARGET MyTest POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E copy_directory
        "${PROJECT_SOURCE_DIR}/libs/
add_custom_command(TARGET MyTest POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E copy_directory
        "${PROJECT_SOURCE_DIR}/libs/$<CONFIGURATION>"
        $<TARGET_FILE_DIR:MyTest>)
lt;CONFIGURATION>"
add_custom_command(TARGET MyTest POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E copy_directory
        "${PROJECT_SOURCE_DIR}/libs/$<CONFIGURATION>"
        $<TARGET_FILE_DIR:MyTest>)
lt;TARGET_FILE_DIR:MyTest>)
После тестирования и подталкивания моего cmake: если вы используетеIMPORTED библиотеки, и нужно переместить библиотеки DLL, вам нужно использовать вариант команды. Если вы добавили свойIMPORTED библиотека какMyImportedLib вы бы использовалиCOMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:MyImportedLib> $<TARGET_FILE_DIR:MyTest> Обратите внимание, что для запуска нескольких команд после сборки необходимо, чтобы все они были объединены в одну пользовательскую команду, напримерadd_custom_command(TARGET MyTest POST_BUILD COMMAND #your first command# COMMAND #Your second command#)
Краткое замечание о том, что сработало в моем случае, если это поможет кому-то еще в будущем: у меня есть проект статической библиотеки, с которым основной исполняемый файл может ссылаться, и эта библиотека требует копирования DLL, если она добавлена. Так что в этом файле библиотеки CMakeLists.txt я использовал${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/$<CONFIG> для целевого назначения. В противном случае он скопировал бы его в путь сборки библиотеки, который был бесполезен.
$<TARGET_FILE_DIR:MyTest> - что это? Как распечатать информацию, что именно означает
это не цель созданияinstall() директивы для сборки двоичных файлов? Или, может быть, CmakeLIBRARY вещи? Я действительно не знаю цепочку инструментов.
Если я что-то пропустил, когда интегрировал команду, этот метод не работает для библиотек, добавленных сIMPORTED_LIBRARIES, Он жалуется на невозможность выполнить команду после сборки, когда ничего не было построено.

Похожие вопросы