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

如何在CMake中根据目标名称列表获取对应的目标文件名列表?

解决CMake批量获取可执行目标文件路径的问题

我来帮你搞定这个CMake的问题~你遇到的target_file-NOTFOUND其实是因为配置阶段和生成阶段的时机差异,以及你用错了属性,下面给你详细解释和解决方法:

为什么你的方法会失败?

你用get_target_property获取RUNTIME_OUTPUT_NAME有两个核心问题:

  1. RUNTIME_OUTPUT_NAME只是可执行文件的文件名(默认和目标名一致,除非你手动设置过),并不是完整的文件路径。
  2. 更关键的是:$<TARGET_FILE:target_x>是生成器表达式,它是在CMake的生成阶段(也就是生成Makefile/VS工程之后)才会被解析成实际路径的;而get_target_property是在配置阶段(你运行cmake ..的时候)执行的,这时候CMake还没确定最终的输出路径(比如Debug/Release的子目录、平台相关的后缀),所以自然拿不到有效结果。

正确的批量处理方式

方法一:用生成器表达式批量收集(推荐,最可靠)

我们不需要在配置阶段强行解析路径,而是把生成器表达式本身存入列表,让CMake在生成阶段自动替换成实际路径。这种方式能完美适配跨平台、不同构建类型的路径差异。

示例代码:

set(EXAMPLE_EXECUTABLES_TARGETS "target_a" "target_b" "target_c" "target_d" "target_e")
set(EXAMPLE_EXECUTABLES "")

foreach(target ${EXAMPLE_EXECUTABLES_TARGETS})
    # 把生成器表达式添加到列表,不做即时解析
    list(APPEND EXAMPLE_EXECUTABLES "$<TARGET_FILE:${target}>")
endforeach()

# 举个例子:用自定义目标打印所有可执行文件路径(生成阶段会自动解析表达式)
add_custom_target(print_all_executables
    COMMAND ${CMAKE_COMMAND} -E echo "All executable paths: ${EXAMPLE_EXECUTABLES}"
    VERBATIM
)

当你构建print_all_executables目标时,就能看到每个目标的完整可执行文件路径了。这种方式也适用于add_custom_command等需要用到可执行文件路径的场景。

方法二:配置阶段获取路径(不推荐,仅特殊场景使用)

如果你确实需要在配置阶段(比如cmake ..时)看到路径,可以结合目标的输出目录和平台后缀来拼接,但要处理多配置生成器(比如VS)的情况:

set(EXAMPLE_EXECUTABLES_TARGETS "target_a" "target_b" "target_c" "target_d" "target_e")

foreach(target ${EXAMPLE_EXECUTABLES_TARGETS})
    # 获取目标的运行时输出目录(优先目标自定义的,其次全局默认)
    get_target_property(runtime_dir ${target} RUNTIME_OUTPUT_DIRECTORY)
    if(NOT runtime_dir)
        set(runtime_dir ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
    endif()

    # 处理多配置生成器(如VS)的不同构建类型目录
    if(CMAKE_CONFIGURATION_TYPES)
        foreach(config ${CMAKE_CONFIGURATION_TYPES})
            string(TOUPPER ${config} CONFIG_UPPER)
            # 拼接完整路径:目录 + 构建类型子目录 + 目标名 + 平台后缀
            set(target_file "${runtime_dir}/${config}/${target}${CMAKE_EXECUTABLE_SUFFIX}")
            message(STATUS "Target ${target} (${config}): ${target_file}")
        endforeach()
    else()
        # 单配置生成器(如Makefile)直接拼接
        set(target_file "${runtime_dir}/${target}${CMAKE_EXECUTABLE_SUFFIX}")
        message(STATUS "Target ${target}: ${target_file}")
    endif()
endforeach()

这种方法的缺点是需要手动处理各种特殊情况(比如自定义输出文件名、不同配置的输出目录),不如生成器表达式灵活可靠。

总结

优先选择生成器表达式的方式,它是CMake设计用来处理这类跨阶段路径问题的最佳实践,能帮你避免很多平台和构建类型的坑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 14:43:10