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




build directory (6)

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?


Answers

I put these lines in my top-level CMakeLists.txt file. All the libraries and executables will be placed in the top level of the build directory so that the executables can find the libraries and it is easy to run everything.

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

You can also use the command find_library:

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

With a defined EXECUTABLE_PATH, for instance:

set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)

you could move the .dll files that your executable need, with

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

An addendum to the accepted answer, added as a separate answer so I get code formatting:

If you are building your dlls in the same project, they will usually be in Release, Debug, etc. directories. You'll have to use the Visual Studio environment variables to correctly copy them. e.g.:

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

for the source and

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

for the destination. Note the escaping!

You can't use the CMake CMAKE_BUILD_TYPE variable for the configuration since it's resolved at VS project generation time and will always be whatever the default is.


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

You probably need to add custom target and make it depend on one of your executable targets. To copy file using above function use

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


CMake produces Visual Studio Projects and Solutions seamlessly. You can even produce projects/solutions for different Visual Studio versions without making any changes to the CMake files.

Adding and removing source files is just a matter of modifying the CMakeLists.txt which has the list of source files and regenerating the projects/solutions. There is even a globbing function to find all the sources in a directory (though it should be used with caution).

The following link explains CMake and Visual Studio specific behavior very well.

CMake and Visual Studio





dll cmake