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

如何通过CMake将add_custom_command生成文件复制到目标可执行文件相对路径?

解决CMake中复制编译后脚本到目标目录的问题

针对你需要将add_custom_command生成的编译脚本文件复制到可执行文件目录的Resources/Script下的需求,以下是两种可靠的解决方案,能解决你之前遇到的「无法感知脚本变更」「不必要复制」的问题:

方案一:改进POST_BUILD自定义命令

通过给POST_BUILD命令添加依赖,让CMake仅在编译后的脚本文件更新时执行复制操作,同时避免不必要的文件拷贝:

# 编译源脚本生成目标文件,保留原有的逻辑
add_custom_command(
    OUTPUT ${CompiledFile}
    COMMAND ${ScriptCompiler} ${ScriptFile} -o ${CompiledFile}
    DEPENDS ${ScriptFile}
    COMMENT "编译脚本 ${ScriptFile}"
)

# 可选:若需将编译后的脚本作为静态库资源,保留此步骤(需指定链接语言避免CMake报错)
add_library(CompiledScripts STATIC ${CompiledFile})
set_target_properties(CompiledScripts PROPERTIES LINKER_LANGUAGE CXX)

# 定义主可执行文件
add_executable(Main main.cpp)

# 添加POST_BUILD复制命令,关键新增DEPENDS和copy_if_different
add_custom_command(
    TARGET Main POST_BUILD
    # 先确保目标目录存在
    COMMAND ${CMAKE_COMMAND} -E make_directory "$<TARGET_FILE_DIR:Main>/Resources/Script/$<CONFIG>"
    # 仅当源文件与目标文件不同时才复制
    COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CompiledFile}" "$<TARGET_FILE_DIR:Main>/Resources/Script/$<CONFIG>/$<TARGET_FILE_NAME:${CompiledFile}>"
    # 依赖编译后的脚本文件,仅当该文件更新时才执行复制
    DEPENDS ${CompiledFile}
    COMMENT "将编译后的脚本复制到Main的Resources目录"
)

优势

  • 逻辑简洁,直接绑定到可执行文件的构建流程
  • copy_if_different避免无意义的文件覆盖
  • DEPENDS ${CompiledFile}确保仅在脚本源文件变更(触发CompiledFile更新)时执行复制

方案二:自定义复制目标+明确依赖链

若需要更清晰的文件跟踪逻辑,可通过自定义目标绑定复制操作,避免自定义目标始终处于过期状态:

# 编译源脚本生成目标文件
add_custom_command(
    OUTPUT ${CompiledFile}
    COMMAND ${ScriptCompiler} ${ScriptFile} -o ${CompiledFile}
    DEPENDS ${ScriptFile}
    COMMENT "编译脚本 ${ScriptFile}"
)

add_library(CompiledScripts STATIC ${CompiledFile})
set_target_properties(CompiledScripts PROPERTIES LINKER_LANGUAGE CXX)

add_executable(Main main.cpp)

# 定义复制后的目标文件路径(含配置目录,适配Debug/Release等不同构建配置)
set(CopiedScriptFile "$<TARGET_FILE_DIR:Main>/Resources/Script/$<CONFIG>/$<TARGET_FILE_NAME:${CompiledFile}>")

# 定义复制操作的自定义命令,输出为目标路径的文件
add_custom_command(
    OUTPUT ${CopiedScriptFile}
    COMMAND ${CMAKE_COMMAND} -E make_directory "$<TARGET_FILE_DIR:Main>/Resources/Script/$<CONFIG>"
    COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CompiledFile}" "${CopiedScriptFile}"
    DEPENDS ${CompiledFile}
    COMMENT "将编译后的脚本复制到Main的Resources目录"
)

# 创建自定义目标,依赖复制后的文件(ALL参数确保默认构建时执行)
add_custom_target(CopyScript ALL DEPENDS ${CopiedScriptFile})

# 让主可执行文件依赖复制目标,确保复制完成后再构建Main
add_dependencies(Main CopyScript)

优势

  • 通过OUTPUT跟踪复制后的文件,CMake会自动判断是否需要重新执行复制操作,避免目标始终过期
  • 依赖链清晰:Main → CopyScript → CopiedScriptFile → CompiledFile → ScriptFile,源脚本变更会触发全流程更新

为什么之前的方案失效?

  • add_custom_target问题:之前未通过OUTPUT或BYPRODUCTS跟踪复制后的文件,导致CMake认为目标始终过期;且未正确设置依赖链,应让自定义目标依赖CompiledFile,再让Main依赖自定义目标。
  • POST_BUILD问题:之前未添加DEPENDS ${CompiledFile},导致无论编译后的脚本是否更新,每次构建都会执行复制操作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 04:21:01