1

我想自动将 GLSL 着色器构建到 SPIR-V,然后使用 CMake 将它们复制到可执行目标的位置。为此,我创建了以下函数:

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 "$<TARGET_FILE:${target_name}>/../${path_in_raw}.spv")
        add_custom_command(OUTPUT ${path_out}
            COMMAND glslc ${path_in} -o ${path_out}
            WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
            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()

它需要一个目标名称和一个 GLSL 文件列表作为参数。我这样调用它:

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

我希望这能够编译basic.vert并编译到位于同一目录中的basic.frag相应文件。不幸的是,我收到以下错误:.spvmini-vk.exe

[cmake] CMake Error at CMakeLists.txt:9 (add_custom_command):
[cmake]   Error evaluating generator expression:
[cmake] 
[cmake]     $<TARGET_FILE:mini-vk>
[cmake] 
[cmake]   No target "mini-vk"
[cmake] Call Stack (most recent call first):
[cmake]   CMakeLists.txt:26 (target_shaders)

我不确定为什么没有“没有目标mini-vk”,因为它是在上面的行中创建的target_shaders

为清楚起见,如果我通过更改以下定义手动键入输出路径,则代码确实有效path_out

set(path_out "${CMAKE_CURRENT_SOURCE_DIR}/build/Debug/${path_in_raw}.spv")

不过,我不想使用这个 hack。

4

1 回答 1

1

这是一个涉及邮票文件的解决方案。与其使用“真实”路径作为 ,不如OUTPUT使用一个空文件作为其时间戳,然后继续使用TARGET_FILE_DIR生成器表达式运行您真正想要的命令。

cmake_minimum_required(VERSION 3.21)
project(test)

find_package(Vulkan REQUIRED)

function(target_shaders name)
  set(shaders "")

  foreach (input IN LISTS ARGN)
    # Might want to add code to handle clashing names 
    # in different directories (e.g. ./basic.vert and
    # ./subdir/basic.vert)
    cmake_path(GET input FILENAME stem)
    cmake_path(ABSOLUTE_PATH input
               BASE_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
               NORMALIZE)
    add_custom_command(
      OUTPUT "${stem}.stamp"
      COMMAND Vulkan::glslc "${input}" -o "$<TARGET_FILE_DIR:${name}>/${stem}.spv"
      COMMAND "${CMAKE_COMMAND}" -E touch "${stem}.stamp"
      DEPENDS "${input}"
    )
    list(APPEND shaders "${stem}.stamp")
  endforeach ()

  add_custom_target("${name}.shaders" DEPENDS ${shaders})
  add_dependencies("${name}" "${name}.shaders")
endfunction()

# Just to test changing the output directory
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY bin)

add_executable(mini-vk main.cpp)
target_shaders(mini-vk basic.vert "${CMAKE_CURRENT_SOURCE_DIR}/basic.frag")
于 2021-08-28T23:27:31.310 回答