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

CMake:如何为已有目标构建仅按需更新的额外文件?

解决CMake主目标按需生成额外文件的问题

核心问题分析

你遇到的两个痛点本质是CMake对目标和文件的依赖处理逻辑不同:

  • add_custom_target本身没有输出文件,CMake无法通过时间戳判断它是否过时,所以每次构建都会执行命令
  • add_dependencies只能接受CMake目标作为依赖项,不能直接关联add_custom_command生成的普通文件

正确解决方案:结合add_custom_command和add_custom_target

通过“自定义命令生成文件 + 自定义目标关联文件”的组合,既能实现依赖跟踪,又能让主目标触发文件生成:

function(register_translation_files)
    # 解析传入参数
    set(options "")
    set(oneValueArgs TARGET)
    set(multiValueArgs INPUT)
    cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})

    set(TARGET ${ARG_TARGET})
    set(INPUT_FILES ${ARG_INPUT})

    foreach (LANG IN LISTS TRANSLATION_LANGUAGES)
        message ("Add translation '${LANG}' for target ${TARGET}")
        set(XLF_FILE "${TARGET}_${LANG}.xlf")

        # 定义生成文件的命令,实现依赖跟踪
        add_custom_command(
            OUTPUT ${XLF_FILE}
            COMMAND scripts/cet2xlf.py --language ${LANG} ${XLF_FILE} ${INPUT_FILES}
            DEPENDS ${INPUT_FILES}
            WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
            COMMENT "Generating translation file ${XLF_FILE}"
        )

        # 创建自定义目标,依赖生成的文件(避免文件名冲突,增加前缀)
        set(TARGET_NAME "${TARGET}_${LANG}_xlf_target")
        add_custom_target(
            ${TARGET_NAME}
            ALL  # 让这个目标默认被构建
            DEPENDS ${XLF_FILE}
        )

        # 让主目标依赖这个自定义目标
        add_dependencies(${TARGET} ${TARGET_NAME})
    endforeach()
endfunction()

# 使用示例
add_executable(MainTarget foo.cpp bla.cpp)
register_translation_files(TARGET MainTarget INPUT file1 file2)

为什么这个方案有效

  1. add_custom_command负责具体的文件生成逻辑,通过DEPENDS跟踪输入文件的变化,只有当输入文件更新时,才会重新运行脚本生成新的XLF文件
  2. 自定义目标${TARGET_NAME}依赖生成的XLF文件,CMake会检查XLF文件的时间戳:如果文件已经是最新的,这个目标不会执行任何操作
  3. 主目标依赖这个自定义目标,保证构建主目标时会自动触发文件生成,且完全遵循依赖更新规则

对之前错误写法的补充说明

  • 直接用add_dependencies(${TARGET} ${XLF_FILE})报错,是因为add_dependencies的第二个参数必须是CMake目标(比如add_executable/add_library/add_custom_target创建的对象),不能是普通文件
  • 纯add_custom_target每次执行,是因为它没有关联任何输出文件,CMake无法验证它的“最新状态”,只能默认每次都执行命令

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 03:10:56