如何使用add_custom_command使用生成器表达式复制dll



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

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_commandgenerator表达式中犯了错误?我希望函数是通用的,这样我想在解决方案中得到的任何dll都会在编译过程中放在目标中。

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

以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根路径是在QTDIR cmake或环境变量中设置的
  • 您的可执行目标名称存储在变量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提出了一些非常有用的建议,使共享库复制跨平台。将regexs替换为file(TO_NATIVE_PATH),将后缀替换为cmake变量,将copy命令替换为cmike命令行副本,得到:

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版本才起作用。对于旧版本,可以使用包含特定于平台的复制命令的变量。

最新更新