2

我必须在编译时在我的解决方案中复制 dll,所以我使用 add_custom_command 如下:

function(dll_dependencies TEST_CASE )
foreach(depencency ${ARGN})        
    add_custom_command(TARGET ${TEST_CASE} POST_BUILD
        COMMAND ${CMAKE_COMMAND} -E copy
        $<DLL_FILE_NAME:${depencency}>)
endforeach()
endfunction()

在 cmakelist.txt 中,我将上述函数称为:

dll_dependencies(performance QT5::Core QT5::FileSystem)

但我收到错误:

Error evaluating generator expression:
$<DLL_FILE_NAME:QT5::Core>

Error evaluating generator expression:
$<DLL_FILE_NAME:QT5::FileSystem>

所以,我不知道它无法到达安装 qt 相关内容的位置,还是我在 add_custom_command 生成器表达式中犯了错误?我希望该函数非常通用,以至于我想在解决方案中获得的任何 dll 在编译期间都放在目标中。

4

1 回答 1

4

您将无法以通用方式管理所有依赖项,因为这不是通用问题,而且我认为尝试它甚至不是一个好主意。

以 Qt 为例(这是您问题中提到的唯一依赖项)。在 Windows 上,复制 Qt dll 依赖项的正确方法是运行windeployqt.exe. 您需要做的不仅仅是复制 dll 来让 Qt 应用程序运行,还有一些目录结构/依赖项必须完全镜像到您的二进制目录中。windeployqt为你做这一切。以任何其他方式管理 Qt dll 依赖项都是一个坏主意。没有理由与工具作斗争或重新发明轮子。

这是我运行的自定义构建步骤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()

它找到它,然后将其作为构建后步骤运行。简单的。

它假设:

  • 您的 Qt 根路径在QTDIRcmake 或环境变量中设置。
  • 您的可执行目标名称存储在变量中TARGET_NAME

更一般地(对于 Windows,cmake < 3.5):

对于非 qt dll(在本例中为 qwt),我有这样的步骤:

# 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"
)

通常这是可行的,但它也可能会复制很多垃圾。请注意,您仍然需要知道在哪里可以找到 Dll(在 中指定${QWT_DIR})。环境变量可能是你的朋友,

如果您愿意,您可能也可以使用${CMAKE_COMMAND} -E copy,或者将其转换为接收 dll 库位置的函数。

更通用(cmake >= 3.5):

@Florian 为使共享库复制步骤跨平台提供了一些非常有用的建议。将正则表达式替换为file(TO_NATIVE_PATH),将后缀替换为 cmake 变量,将copy命令替换为 cmake 命令行副本,您将获得:

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

如评论中所述,在 cmake -E copy 中使用通配符(*)直到 3.5 版才有效。对于旧版本,可以使用包含特定于平台的复制命令的变量。

于 2016-05-02T14:32:50.510 回答