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

CMake中如何为已创建的custom_target()添加依赖项?

问题描述

需要创建名为sdk_extraction的顶层目标,使其每次构建/测试都会执行,该目标依赖一批从项目文件复制或轻微转换生成的文件。已将待导出文件列表存为全局属性列表,尝试两种实现方式:

方式1:先创建目标再添加依赖(报错)

先通过add_custom_target()创建sdk_target,再遍历文件生成custom_command,用add_dependencies()给目标添加依赖,报错“依赖目标不存在”。

代码示例:

function(finalize_sdk_export destination)
    file(REAL_PATH ${destination} destination )

    add_custom_target(sdk_target ALL
        COMMENT "Exporting SDK"
        )

    get_property(sdk_source GLOBAL PROPERTY SDK_SOURCE )
    string(REPLACE " " ";" sdk_source "${sdk_source}")
    foreach (item ${sdk_source})
        string(REPLACE ${destination} ${destination}/sdk target "${item}")
        add_custom_command(
            OUTPUT ${target}
            DEPENDS ${item}
            COMMAND ${CMAKE_COMMAND} -E copy ${item} ${target}
            VERBATIM
        )
        add_dependencies(sdk_target ${target})
    endforeach()
endfunction()

报错信息:

CMake Error at <redacted>/build_scripts/CMakeLists.txt:209 (add_dependencies):
  The dependency target
  "<redacted>/sdk/CMakeLists.txt"
  of target "sdk_target" does not exist.
Call Stack (most recent call first):
  <redacted>/CMakeLists.txt:78 (finalize_sdk_export)

方式2:先收集输出文件再创建目标(正常工作,但担心性能)

先遍历生成所有custom_command并收集输出文件列表,创建custom_target时通过DEPENDS参数指定所有依赖,可正常运行,但担心文件数量达数百/数千个时出现问题。

代码示例:

function(finalize_sdk_export destination)
    file(REAL_PATH ${destination} destination )

    get_property(sdk_source GLOBAL PROPERTY SDK_SOURCE )
    string(REPLACE " " ";" sdk_source "${sdk_source}")
    foreach (item ${sdk_source})
        string(REPLACE ${destination} ${destination}/sdk target "${item}")
        add_custom_command(
            OUTPUT ${target}
            DEPENDS ${item}
            COMMAND ${CMAKE_COMMAND} -E copy ${item} ${target}
            VERBATIM
        )
        list(APPEND sdk_files ${target})
    endforeach()
    add_custom_target(sdk_target ALL
        COMMENT "Exporting SDK"
        DEPENDS ${sdk_files}
        )
endfunction()

注:已放弃CMake内置的install/export功能,因为需要严格控制目录结构和CMake文件样式。


正确实现方案

方式1报错原因

add_dependencies()仅接受CMake目标作为参数——即通过add_executable、add_library或add_custom_target创建的实体,而你传入的${target}是生成文件的路径,并非CMake目标,因此会提示“依赖目标不存在”。add_custom_command生成的输出文件,只能通过自定义目标的DEPENDS参数关联,不能用add_dependencies。

方式2是标准且可靠的实现

方式2是CMake中关联自定义命令输出与自定义目标的标准用法,完全无需担心文件数量问题。CMake内部对大量依赖项的处理做了优化,哪怕是数千个文件,只要路径有效、无重复,就能稳定运行。

可选优化点

若想提升代码效率或可维护性,可考虑:

  • 若源文件符合特定路径/命名规则,用file(GLOB_RECURSE ... CONFIGURE_DEPENDS)(CMake 3.12+支持)批量收集文件,减少手动维护全局属性的工作量,CONFIGURE_DEPENDS可自动检测新增文件。
  • 对于需要转换的文件,将转换逻辑封装成独立脚本或CMake函数,在add_custom_command中调用,让代码结构更清晰。

最终推荐代码

直接采用方式2的实现即可,若要将目标名改为需求中的sdk_extraction,仅需修改add_custom_target的第一个参数:

function(finalize_sdk_export destination)
    file(REAL_PATH ${destination} destination )

    get_property(sdk_source GLOBAL PROPERTY SDK_SOURCE )
    string(REPLACE " " ";" sdk_source "${sdk_source}")
    foreach (item ${sdk_source})
        string(REPLACE ${destination} ${destination}/sdk target "${item}")
        add_custom_command(
            OUTPUT ${target}
            DEPENDS ${item}
            COMMAND ${CMAKE_COMMAND} -E copy ${item} ${target}
            VERBATIM
        )
        list(APPEND sdk_files ${target})
    endforeach()
    add_custom_target(sdk_extraction ALL
        COMMENT "Exporting SDK"
        DEPENDS ${sdk_files}
        )
endfunction()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 19:55:31