cmake不在自定义命令中复制文件

cmake does not copy file in custom command

我想将 qml 文件从源目录复制到构建目录。以下脚本仅在第一次运行良好。当我更改任何 *.qml 文件和 运行 make 时,它​​们不会复制到构建文件夹,也不会更新。我做错了什么?

file(GLOB_RECURSE SOURCES *.cpp)
file(GLOB_RECURSE QMLS *.qml)

add_library(MyLib SHARED ${SOURCES} ${QMLS})

foreach(QmlFile ${QMLS})
  add_custom_command(TARGET MyLib POST_BUILD
                     COMMAND ${CMAKE_COMMAND} -E copy_if_different
                     ${QmlFile} $<TARGET_FILE_DIR:MyLib>)
endforeach()

您正在使用 add_custom_commandTARGET 签名,这意味着命令是作为构建 TARGET 的一部分执行的。在您的情况下,POST_BUILD,这意味着在 MyLib 的构建完成后,命令将是 运行。如果 MyLib 是最新的并且不需要重新构建,命令将不会 运行。

您可能想改用输出生成签名 (OUTPUT)。像这样:

set(copiedQmls "")
foreach(QmlFile ${QMLS})
  get_filename_component(nam ${QmlFile} NAME)
  add_custom_command(
    OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${nam}
    COMMAND ${CMAKE_COMMAND} -E copy_if_different ${QmlFile} ${CMAKE_CURRENT_BINARY_DIR}
    DEPENDS ${QmlFile}
    COMMENT "Copying ${QmlFile}"
    VERBATIM
  )
  list(APPEND copiedQmls ${CMAKE_CURRENT_BINARY_DIR}/${nam})
endforeach()

add_custom_target(
  CopyQMLs ALL
  DEPENDS ${copiedQmls}
)

请注意,不幸的是,add_custom_commandOUTPUT 参数不支持生成器表达式,因此不能在那里使用 $<TARGET_FILE_DIR>。我在上面的示例中使用了 ${CMAKE_CURRENT_BINARY_DIR},您可能需要自定义它以满足您的需要。 ${CMAKE_CFG_INTDIR} 可用于指定多配置生成器的每个配置目录。

请注意我上面的代码中存在额外的自定义目标。这是必要的,因为 CMake 只会在某些内容依赖于该输出时执行生成输出的自定义命令。自定义命令通过在其 DEPENDS 部分中列出输出来做到这一点。

虽然 Angew 的 很好,但可以消除额外 target 的使用。为此,add_library 调用应该使用 copied .qml 文件(而不是 original 文件,就像在脚本中一样问题 post):

# This part is same as in Angew's answer
set(copiedQmls "")
foreach(QmlFile ${QMLS})
  get_filename_component(nam ${QmlFile} NAME)
  add_custom_command(
    OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${nam}
    COMMAND ${CMAKE_COMMAND} -E copy_if_different ${QmlFile} ${CMAKE_CURRENT_BINARY_DIR}
    DEPENDS ${QmlFile}
    COMMENT "Copying ${QmlFile}"
    VERBATIM
  )
  list(APPEND copiedQmls ${CMAKE_CURRENT_BINARY_DIR}/${nam})
endforeach()

# But instead of creating new target, we reuse library one.
add_library(MyLib SHARED ${SOURCES} ${copiedQmls})

当构建库 target 时,它会触发 non-sources 文件在 add_library 调用中被更新(如果有对应于 add_custom_command 调用),但是 更新非源文件不会强制重建库 文件 。这就是您的原始代码无法按预期工作的原因。

注意,因为 .qml 文件不被 CMake 识别为来源,您 不需要 设置 GENERATED 属性他们,如前所述 here.