You're not going to be able to manage all dependencies in a generic way, because it's not a generic problem, and I'll contend that it's not even a good idea to try.
Take Qt for example (which are the only dependencies mentioned in your question). On windows, the right way to copy Qt dll dependencies is to run windeployqt.exe
. You need to do more than just copy dll's to get Qt apps to run, there are directory structures/dependencies that have to be mirrored exactly in your binary directory. windeployqt
does all that for you. Managing the Qt dll dependencies any other way is a Bad Idea. There is no reason to fight the tool or reinvent the wheel.
Here's my custom build step for running windeployqt
:
# Windows specific build steps
if(WIN32)
# Run winddeployqt if it can be found
find_program(WINDEPLOYQT_EXECUTABLE NAMES windeployqt HINTS ${QTDIR} ENV QTDIR PATH_SUFFIXES bin)
add_custom_command(TARGET ${TARGET_NAME} POST_BUILD
COMMAND ${WINDEPLOYQT_EXECUTABLE} $<TARGET_FILE:${TARGET_NAME}>)
endif()
It finds it, then runs it as a post-build step. Simple.
It assumes:
- Your Qt root path is set in the
QTDIR
cmake or environment variable.
- your executable target name is stored in the variable
TARGET_NAME
More generically (for windows, cmake < 3.5):
For non-qt dll's (in this case qwt), I have a step like this:
# on windows, to copy, we need to replace the pesky forward slashes with back slashes
STRING(REGEX REPLACE "/" "\\\\" copySource \"${QWT_DIR}/lib/*.dll\")
STRING(REGEX REPLACE "/" "\\\\" copyDest \"${CMAKE_CURRENT_BINARY_DIR}/$<CONFIGURATION>\")
# Copy
ADD_CUSTOM_COMMAND( TARGET ${TARGET_NAME}
POST_BUILD
COMMAND COMMAND copy ${copySource} ${copyDest}
COMMENT "Copying Qwt dll's...\n"
)
Usually that works, but it also probably copies a lot of garbage. Notice, you still need to know where to find the Dll's (specified in ${QWT_DIR}
). Environment variables could be your friend,
You can probably also use ${CMAKE_COMMAND} -E copy
if you like, or turn it into a function that takes in the dll lib location.
Even more generically (cmake >= 3.5):
@Florian made some very helpful suggestions for making the shared-library copy step cross-platform. Replacing the regexs with file(TO_NATIVE_PATH)
, the suffixes with cmake variables, and the copy
command with the cmake command-line copy, you get:
file(TO_NATIVE_PATH "${QWT_DIR}/lib/*.${CMAKE_SHARED_LIBRARY_SUFFIX}" copy_source)
set(copy_dest "$<TARGET_FILE_DIR:${TARGET_NAME}>")
# perform copy
ADD_CUSTOM_COMMAND(TARGET ${TARGET_NAME}
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy ${copySource} ${copyDest}
)
As mentioned in the comments, using wildcard(*) in cmake -E copy was not working until version 3.5. For older versions, a variable containing the platform-specific copy command could be used.