How to copy DLL files into the same folder as the executable using CMake?

Mat picture Mat · May 20, 2012 · Viewed 65.7k times · Source

We use CMake for generating the Visual Studio files of our sources in our SVN. Now my tool requires some DLL files to be in the same folder as the executable. The DLL files are in a folder alongside the source.

How can I change my CMakeLists.txt such that the generated Visual Studio project will either have already the particular DLL files in the release/debug folders or will copy them upon compilation?

Answer

Fraser picture Fraser · May 20, 2012

I'd use add_custom_command to achieve this along with cmake -E copy_if_different.... For full info run

cmake --help-command add_custom_command
cmake -E


So in your case, if you have the following directory structure:

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

and your CMake target to which the command applies is MyTest, then you could add the following to your 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
        $<TARGET_FILE_DIR:MyTest>)                 # <--this is out-file path


If you just want the entire contents of the /libs/ directory copied, use cmake -E copy_directory:

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


If you need to copy different dlls depending upon the configuration (Release, Debug, eg) then you could have these in subdirectories named with the corresponding configuration: /libs/Release, and /libs/Debug. You then need to inject the configuration type into the path to the dll in the add_custom_command call, like this:

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