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_command
的 TARGET
签名,这意味着命令是作为构建 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_command
的 OUTPUT
参数不支持生成器表达式,因此不能在那里使用 $<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.
我想将 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_command
的 TARGET
签名,这意味着命令是作为构建 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_command
的 OUTPUT
参数不支持生成器表达式,因此不能在那里使用 $<TARGET_FILE_DIR>
。我在上面的示例中使用了 ${CMAKE_CURRENT_BINARY_DIR}
,您可能需要自定义它以满足您的需要。 ${CMAKE_CFG_INTDIR}
可用于指定多配置生成器的每个配置目录。
请注意我上面的代码中存在额外的自定义目标。这是必要的,因为 CMake 只会在某些内容依赖于该输出时执行生成输出的自定义命令。自定义命令通过在其 DEPENDS
部分中列出输出来做到这一点。
虽然 Angew 的 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.