将可执行文件链接到的所有 dll 复制到可执行目录

问题描述 投票:0回答:2

这个问题询问类似的问题,但只需要手动指定要复制哪些dll。我的问题是:有没有一种方法可以简单地让 CMake 复制链接到可执行库的所有 dll,而无需手动告诉 CMake 要复制哪些文件?有时 CMake 更了解是否需要 dll。例如,在安装了同一库(例如Boost)的dll和静态库的系统中,并且我们选择静态链接到Boost,那么我们不需要复制dll。因此,与手动指定要复制哪些文件相比,CMake 可以做出更好的决定。另一个例子是,我的QT库链接到ICU库,并且在编写CMakeLists.txt时,我对此一无所知,所以我不可能告诉CMake复制ICU dll,所以这应该由CMake而不是完成人类。

假设操作系统是Windows。

dll cmake
2个回答
6
投票

从 CMake 3.21 开始,生成器表达式

$<TARGET_RUNTIME_DLLS:...>
很有帮助。它扩展到其传递依赖项中所有
SHARED
库的位置的路径列表(以未指定的顺序)。

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

上面的代码假设

$<TARGET_RUNTIME_DLLS:...>
不会为空,因此检查我们是否在DLL系统上(
CMAKE_IMPORT_LIBRARY_SUFFIX
仅在这种情况下定义)。如果它空,则该命令将失败,因为没有足够的参数提供给
cmake -E copy
。我个人提出了一个关于其不良人体工程学的问题。 https://gitlab.kitware.com/cmake/cmake/-/issues/23543

请注意,

$<TARGET_RUNTIME_DLLS:...>
仅捕获CMake目标。这是一个很好的例子,说明了为什么“仅”链接到 CMake 目标通常是一个好主意,即使这意味着您自己创建一个导入的目标。

如果你发现自己写了很多,你可以将它包装成一个函数:

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

然后只需拨打上面的
copy_runtime_dlls(exe)

即可。

    


1
投票
BundleUtilities.cmake

,它提供了

fixup_bundle(...)
详情可以在这里找到:

https://gitlab.kitware.com/cmake/community/-/wikis/doc/cpack/BundleUtilities

http://www.cmake.org/cmake/help/v2.8.8/cmake.html#module:BundleUtilities

© www.soinside.com 2019 - 2024. All rights reserved.