Preliminary information: I'm stuck on CMake 3.19!
I have a project with many subprojects that build DLLs and excutables. I want all DLL and EXE files to end up in the build directory. I could already realize this by:
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
DLLs from external libraries should also be copied. I have four ways I include 3rdparty libraries:
- Header Only libraries via:
add_library(Eigen3 INTERFACE) target_include_directories(Eigen3 INTERFACE "/path/to/include") add_library(Eigen3::Eigen3 ALIAS Eigen3) - Binary DLL/LIB Files plus headers:
add_library(FreeImage SHARED IMPORTED) target_include_directories(FreeImage INTERFACE "/path/to/include") set_property(TARGET FreeImage PROPERTY IMPORTED_LOCATION "/path/to/FreeImage.dll") set_property(TARGET FreeImage PROPERTY IMPORTED_IMPLIB "/path/to/FreeImage.lib") add_library(FreeImage::FreeImage ALIAS FreeImage) - Standard
find_packagewith targets as result:find_package(Qt5 COMPONENTS Core REQUIRED) - Direct specification of the DLL name in
target_link_library.
I link my project via target_link_library to the targets of the libraries:
add_executable(my_binary main.cpp)
target_link_libraries(my_binary
Eigen3::Eigen3
FreeImage::FreeImage
Qt5::Core
version) # version.dll from windows/system32
I want all DLL files of the direct dependencies of my_binary to be copied to ${CMAKE_BINARY_DIR} after the build.
What I tried:
function(update_dependencies PROJECT_NAME)
get_target_property(LINK_LIBRARIES ${PROJECT_NAME} LINK_LIBRARIES)
foreach(LINK_LIBRARY IN ITEMS ${LINK_LIBRARIES})
if(NOT TARGET ${LINK_LIBRARY})
continue()
endif()
get_target_property(TARGET_FILE ${LINK_LIBRARY} IMPORTED_LOCATION)
if(NOT TARGET_FILE)
continue()
endif()
message(STATUS "TARGET_FILE: ${TARGET_FILE}")
endforeach()
endfunction()
update_dependencies(my_binary)
Output:
TARGET_FILE: /path/to/FreeImage.dll
This approach works only for IMPORTED libraries. The Qt core DLL included via find_package is not printed.
Because of CMP0026, it seems I cannot simply query LOCATION instead of IMPORTED_LOCATION. When I enable the old behavior, it works the way I want in release mode. In the debug build it links against the Qt debug DLL, but it copies the Qt release DLL.
I also tried to work with add_custom_command and $<TARGET_FILE:${LINK_LIBRARY}>. The problem is that I seem to be able to query TARGET_FILE only if there is also a TARGET_FILE. Also, of course, I only want to execute the command if a TARGET_FILE exists.