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_package
with 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.