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

如何使用CMake将编译产物放置到目标可执行文件的同级目录

问题根因

你遇到的报错是因为 add_custom_command 的 OUTPUT 参数不支持使用带目标引用的生成器表达式。CMake 在配置阶段解析 add_custom_command 时,需要提前确定输出文件的路径,而 $<TARGET_FILE:${target_name}> 这类生成器表达式要到构建系统生成阶段才会求值,因此 CMake 无法在配置阶段识别出你已经创建了 mini-vk 目标,才会抛出目标不存在的错误。

另外你写法里用 $<TARGET_FILE:${target_name}>/../ 来取目标目录也不规范,CMake 提供了专门的生成器表达式 $<TARGET_FILE_DIR:${target_name}> 直接获取目标文件的所在目录。


最优修复方案

不需要硬编码路径,完全跟随目标的输出目录自动适配,同时支持增量编译:

function(target_shaders target_name)
    # 取除第一个参数外的所有入参作为着色器路径列表,无需手动封装引号
    set(shader_paths ${ARGN})
    add_custom_target("${target_name}_shaders"
        COMMENT "Compiling GLSL shaders for ${target_name}"
        VERBATIM
    )

    foreach(path_in_raw ${shader_paths})
        set(path_in "${CMAKE_CURRENT_SOURCE_DIR}/${path_in_raw}")
        # 直接用专用生成器表达式获取目标输出目录
        set(path_out "$<TARGET_FILE_DIR:${target_name}>/${path_in_raw}.spv")
        # 改用 TARGET 型自定义命令,COMMAND 字段支持生成器表达式
        add_custom_command(TARGET "${target_name}_shaders"
            PRE_BUILD
            COMMAND glslc ${path_in} -o ${path_out}
            MAIN_DEPENDENCY ${path_in}
            COMMENT "Compiling GLSL shader ${path_in}"
        )
    endforeach()

    add_dependencies(${target_name} "${target_name}_shaders")
endfunction()

对应的调用方式也可以简化,不需要用引号包裹着色器列表:

add_executable(mini-vk main.cpp)
target_shaders(mini-vk basic.vert basic.frag)

可选适配方案

如果你需要兼容旧版CMake,也可以提前统一设置可执行目标的输出目录,适配多配置生成器(Visual Studio、XCode等):

# 全局设置所有可执行目标的输出目录,多配置生成器会自动追加配置名子目录
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)

function(target_shaders target_name paths_in)
    set(paths_out "")
    foreach(path_in_raw ${paths_in})
        set(path_in "${CMAKE_CURRENT_SOURCE_DIR}/${path_in_raw}")
        # 路径配置阶段即可确定,支持增量编译检测
        set(path_out "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/$<CONFIG>/${path_in_raw}.spv")
        add_custom_command(OUTPUT ${path_out}
            COMMAND glslc ${path_in} -o ${path_out}
            DEPENDS ${path_in}
            COMMENT "Compiling GLSL shader ${path_in}"
        )
        list(APPEND paths_out ${path_out})
    endforeach()

    add_custom_target("${target_name}_shaders" DEPENDS ${paths_out})
    add_dependencies(${target_name} "${target_name}_shaders")
endfunction()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 15:36:03