这个问题询问类似的问题,但只需要手动指定要复制哪些dll。我的问题是:有没有一种方法可以简单地让 CMake 复制链接到可执行库的所有 dll,而不需要手动告诉 CMake 要复制哪些文件?有时 CMake 更了解是否需要 dll。例如,在安装了同一库(例如Boost)的dll和静态库的系统中,并且我们选择静态链接到Boost,那么我们不需要复制dll。因此,与手动指定要复制哪些文件相比,CMake 可以做出更好的决定。另一个例子是,我的QT库链接到ICU库,并且在编写CMakeLists.txt时,我对此一无所知,所以我不可能告诉CMake复制ICU dll,所以这应该由CMake而不是完成人类。
假设操作系统是Windows。
As of CMake 3.21 the generator expression $<TARGET_RUNTIME_DLLS:...>
is helpful. It expands to a list of paths (in an unspecified order) to the locations of all the SHARED
libraries in its transitive dependencies.
add_library(lib1 ...)
add_library(lib2 ...)
find_package(lib3 REQUIRED)
add_executable(exe ...)
target_link_libraries(exe PRIVATE lib1 lib2 imported::lib3)
# The following variable is defined only on DLL systems
if (CMAKE_IMPORT_LIBRARY_SUFFIX)
add_custom_command(
TARGET exe POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_RUNTIME_DLLS:exe> $<TARGET_FILE_DIR:exe>
COMMAND_EXPAND_LISTS
)
endif ()
Run Code Online (Sandbox Code Playgroud)
The above code assumes that $<TARGET_RUNTIME_DLLS:...>
will not be empty, hence the check that we are on a DLL system (CMAKE_IMPORT_LIBRARY_SUFFIX
is only defined when this is the case). If it is empty, the command will fail, as not enough arguments will be supplied to cmake -E copy
. I have personally opened an issue about the bad ergonomics of this. https://gitlab.kitware.com/cmake/cmake/-/issues/23543
Note that $<TARGET_RUNTIME_DLLS:...>
only captures CMake targets. This is a good example of why it is a good idea in general to link only to CMake targets, even if that means creating an imported target yourself.
If you find you're writing this a lot, you can wrap it up into a function:
function(copy_runtime_dlls TARGET)
get_property(already_applied TARGET "${TARGET}" PROPERTY _copy_runtime_dlls_applied)
if (CMAKE_IMPORT_LIBRARY_SUFFIX AND NOT already_applied)
add_custom_command(
TARGET "${TARGET}" POST_BUILD
COMMAND "${CMAKE_COMMAND}" -E copy
"$<TARGET_RUNTIME_DLLS:${TARGET}>" "$<TARGET_FILE_DIR:${TARGET}>"
COMMAND_EXPAND_LISTS
)
set_property(TARGET "${TARGET}" PROPERTY _copy_runtime_dlls_applied 1)
endif ()
endfunction()
Run Code Online (Sandbox Code Playgroud)
Then just call copy_runtime_dlls(exe)
above.
归档时间: |
|
查看次数: |
4705 次 |
最近记录: |