我必须在编译时在我的解决方案中复制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都会在编译期间放在目标中。
答案 0 :(得分: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()
找到它,然后将其作为构建后步骤运行。简单。
它假设:
QTDIR
cmake或环境变量中设置。TARGET_NAME
对于非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 lib位置的函数。
@Florian为跨平台共享库复制步骤提出了一些非常有用的建议。使用file(TO_NATIVE_PATH)
替换正则表达式,使用cmake变量替换带有cmake变量的正则值,使用cmake命令行副本替换copy
命令,可以得到:
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副本中使用通配符(*)在版本3.5之前无效。对于旧版本,可以使用包含特定于平台的复制命令的变量。