You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

add_custom_command的OUTPUT不支持目标生成表达式时,如何实现目标文件副本的依赖跟踪?

解决CMake中自定义命令OUTPUT无法使用目标生成表达式的问题

针对你想要实现的「复制目标文件到指定目录再打包」的需求,有两种实用的解决思路,能避开OUTPUT参数对生成表达式的限制:

方法一:用自定义目标处理文件复制(推荐)

放弃在add_custom_command的OUTPUT中指定带生成表达式的路径,改用自定义目标完成文件复制,再让打包逻辑依赖这个复制目标。这种方式更灵活,且完全兼容各版本CMake:

# 创建用于复制文件到to_zip目录的自定义目标
add_custom_target(copy-files-to-zip
  # 先确保目标目录存在
  COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/to_zip
  # 复制第一个目标文件,这里可以自由使用生成表达式
  COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:Foo> ${CMAKE_BINARY_DIR}/to_zip/
  # 有多个目标的话,继续添加复制命令即可
  COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:Bar> ${CMAKE_BINARY_DIR}/to_zip/
  # 依赖所有需要复制的目标,确保它们先编译完成
  DEPENDS Foo Bar
)

# 定义打包的自定义命令,依赖复制目标而非单个文件
add_custom_command(
  OUTPUT ${CMAKE_BINARY_DIR}/myzip.zip
  # 直接打包整个to_zip目录(这里替换成你实际的zip命令,比如zip/7z等)
  COMMAND zip -r ${CMAKE_BINARY_DIR}/myzip.zip ${CMAKE_BINARY_DIR}/to_zip/
  # 确保复制完成后再打包
  DEPENDS copy-files-to-zip
)

# 最终的打包目标
add_custom_target(create-zip DEPENDS ${CMAKE_BINARY_DIR}/myzip.zip)

为什么这种方法可行?

自定义目标(add_custom_target)的COMMAND参数不受生成表达式的限制,可以自由使用$<TARGET_FILE>这类目标相关的生成表达式。同时,通过让打包命令依赖复制目标,CMake会保证先完成所有文件复制,再执行打包操作。

方法二:利用CMake 3.20+的有限支持(仅适用于特定场景)

如果你使用CMake 3.20及以上版本,官方允许在add_custom_command的OUTPUT中使用部分目标相关生成表达式,比如$<TARGET_FILE_NAME>,但需要注意:生成表达式不能出现在路径的目录部分,只能在文件名部分。示例代码如下:

set(ZIP_DIR ${CMAKE_BINARY_DIR}/to_zip)

add_custom_command(
  OUTPUT ${ZIP_DIR}/$<TARGET_FILE_NAME:Foo>
  DEPENDS Foo
  COMMAND ${CMAKE_COMMAND} -E make_directory ${ZIP_DIR}
  COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:Foo> ${ZIP_DIR}/$<TARGET_FILE_NAME:Foo>
)

# 多个目标的话重复上述add_custom_command,然后收集所有输出文件
list(APPEND ZIP_FILES ${ZIP_DIR}/$<TARGET_FILE_NAME:Foo> ${ZIP_DIR}/$<TARGET_FILE_NAME:Bar>)

add_custom_command(
  OUTPUT ${CMAKE_BINARY_DIR}/myzip.zip
  DEPENDS ${ZIP_FILES}
  COMMAND zip -r ${CMAKE_BINARY_DIR}/myzip.zip ${ZIP_DIR}/
)

add_custom_target(create-zip DEPENDS ${CMAKE_BINARY_DIR}/myzip.zip)

但这种方法有局限性:如果你的目标文件路径包含生成表达式(比如跨平台的不同后缀),目录部分不能用生成表达式,只能固定路径。所以方法一更通用。

内容的提问来源于stack exchange,提问作者user3667089

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 10:17:23