关于包含/依赖项的 GLSLC 的 CMake 调用

Alt*_*ape 5 glsl cmake ninja

我正在使用glslcs #include(不是核心规范 IIRC 的一部分,但在 shaderc 中受支持,它是 背后的引擎glslc,随 LunarG Vulkan SDK 分发)将 GLSL 着色器编译为 Vulkan 和 GL 4.5 的 SPIR-V。发出包含依赖信息的glslcgcc 样式 depsfiles ( ) 文件。[my_shader].[ext].d

我的项目是使用 cmake/ninja/MSVC 2017 构建的。

今天,我使用 cmake在磁盘上的着色器发生更改时custom_command进行调用glslc,作为我的主要目标的构建后步骤。但是,这不会捕获包含文件中的更改(根本不知道 .d 文件或其内容),因此当包含的 glsl 文件发生更改时重建着色器可能会让我自己和团队中的其他人陷入困境。

看起来 ninja 可以调用任意编译器,并且由于 ninja 知道如何处理 depsfiles,我应该能够强制 ninja 运行 glslc - 不确定其他构建系统,因为现在我们对 ninja 进行了标准化。

那么我如何告诉 cmake 配置 ninja 对特定目标使用 glslc 呢?或者有没有一个典型的方法来完成这个任务?它看起来像是一个cmake pull request,以添加对 glslc 的支持,因为编译器在 2016 年左右没有进入 cmake,所以无论我做什么都将是一个解决方法。

dia*_*pir 9

与 ninja 结合使用时,CMake 可以理解 depfile。

数据文件

为 Ninja 生成器指定一个 .d depfile。.d 文件包含通常由自定义命令本身发出的依赖项。将 DEPFILE 与 Ninja 之外的其他生成器一起使用是一个错误。

add_custom_command(
    OUTPUT ${source}.h
    DEPENDS ${source}
    COMMAND
        glslc
        -MD -MF ${source}.d
        -o ${source}.h -mfmt=num
        --target-env=opengl
        ${CMAKE_CURRENT_SOURCE_DIR}/${source}
    DEPFILE ${source}.d
)
Run Code Online (Sandbox Code Playgroud)
add_custom_command(
    OUTPUT ${source}.h
    DEPENDS ${source}
    COMMAND
        glslc
        -MD -MF ${source}.d
        -o ${source}.h -mfmt=num
        --target-env=opengl
        ${CMAKE_CURRENT_SOURCE_DIR}/${source}
    DEPFILE ${source}.d
)
Run Code Online (Sandbox Code Playgroud)

编辑:变得更花哨

find_package(Vulkan COMPONENTS glslc)
find_program(glslc_executable NAMES glslc HINTS Vulkan::glslc)

function(compile_shader target)
    cmake_parse_arguments(PARSE_ARGV 1 arg "" "ENV;FORMAT" "SOURCES")
    foreach(source ${arg_SOURCES})
        add_custom_command(
            OUTPUT ${source}.${arg_FORMAT}
            DEPENDS ${source}
            DEPFILE ${source}.d
            COMMAND
                ${glslc_executable}
                $<$<BOOL:${arg_ENV}>:--target-env=${arg_ENV}>
                $<$<BOOL:${arg_FORMAT}>:-mfmt=${arg_FORMAT}>
                -MD -MF ${source}.d
                -o ${source}.${arg_FORMAT}
                ${CMAKE_CURRENT_SOURCE_DIR}/${source}
        )
        target_sources(${target} PRIVATE ${source}.${arg_FORMAT})
    endforeach()
endfunction()
Run Code Online (Sandbox Code Playgroud)
add_executable(dummy dummy.c)
compile_shader(dummy
    ENV opengl
    FORMAT num
    SOURCES
        dummy.vert
        dummy.frag
)
Run Code Online (Sandbox Code Playgroud)