首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >CMake:如何使add_custom_command只在其依赖项更改时触发自定义命令?

CMake:如何使add_custom_command只在其依赖项更改时触发自定义命令?
EN

Stack Overflow用户
提问于 2022-05-28 19:20:51
回答 1查看 200关注 0票数 1

我的目标中有一些文件(.hlsl)是使用自定义编译器(glslc)编译的。编译后,我使用不同的工具将编译好的二进制文件嵌入到包含c数组like described here的c文件中。

以下代码对此工作流进行了总结,该代码调用2个自定义命令:

代码语言:javascript
运行
复制
function(build_hlsl_shader shader_file)
    get_source_file_property(shader_type ${shader_file} ShaderType)    
    get_filename_component(shader_name ${shader_file} NAME_WE)

    # special command: .hlsl file to a .c / .h file
    add_custom_command(  
        TARGET shaders_custom_target # a custom target
        #OUTPUT ${shader_name}.cpp # maybe this? 
        #DEPENDS ${shader_file} # maybe that?
        MAIN_DEPENDENCY ${shader_file} # or maybe thee?
        COMMAND # special compiler
        ${glslc_executable} 
        -fshader-stage=${shader_type} 
        ${CMAKE_CURRENT_SOURCE_DIR}/${shader_file}
        -o
        ${CMAKE_CURRENT_SOURCE_DIR}/${shader_name}.spv
        COMMAND # special tool that generates the c header.
        bin2h 
        ${CMAKE_CURRENT_SOURCE_DIR}/${shader_name}.spv
    )
endfunction()

然后,我定义了一个自定义目标,它在构建时生成上述文件

代码语言:javascript
运行
复制
add_custom_target(
    shaders_custom_target 
    DEPENDS
    "shader.hlsl"
)

build_hlsl_shader("shader.hlsl")

# this library consumes the headers generated by the first target
add_library(library2 STATIC "file1.cpp""file1.hpp")
add_dependencies(library2  shaders_custom_target)

主要问题是,每当我构建项目时,都会触发自定义目标构建过程,而不考虑任何.hlsl文件都没有被更改。这是不可取的,我希望我的自定义命令像编译常规.c或cpp文件时一样工作。它们只有在更改时才会编译。

我的要求如下:

每次更改一个

  • 文件时,都应该触发自定义命令。当我构建目标/项目时,不应该触发自定义命令。

那么,如何才能做到这一点呢?

我尝试了几种方法,比如使用DEPENDSMAIN_DEPENDENCY或使用OUTPUT而不是TARGET。都没起作用。我还尝试了提供给herehere的解决方案。他们都遭受着同样的问题。

按照注释中的要求,下面是我使用OUTPUT而不是TARGET的尝试

代码语言:javascript
运行
复制
function(build_hlsl_shader shader_file)
    get_source_file_property(shader_type ${shader_file} ShaderType)    
    get_filename_component(shader_name ${shader_file} NAME_WE)

    add_custom_command(
        #TARGET shaders_custom_target
        OUTPUT 
        #${shader_name}.hpp # the generated header, tried with or without
        ${shader_file} # tried with and without
        DEPENDS ${shader_file} # tried with and without
        #MAIN_DEPENDENCY ${shader_file} # tried with and without

        COMMAND
        ${glslc_executable}
        -fshader-stage=${shader_type} 
        ${CMAKE_CURRENT_SOURCE_DIR}/${shader_file}
        -o
        ${CMAKE_CURRENT_SOURCE_DIR}/${shader_name}.spv
        COMMAND
        bin2h
        ${CMAKE_CURRENT_SOURCE_DIR}/${shader_name}.spv
        WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
     )
endfunction()
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-05-31 05:40:50

这取决于您认为着色器是“库的一部分”,还是运行时需要的一些数据。

对于生成HLSL着色器的项目,我使用一个与您所做的类似的自定义目标:

代码语言:javascript
运行
复制
add_custom_target(shaders)

set_source_files_properties(VertexShader.hlsl PROPERTIES ShaderType "vs")
set_source_files_properties(PixelShader.hlsl PROPERTIES ShaderType "ps")
    
foreach(FILE VertexShader.hlsl PixelShader.hlsl)
    get_filename_component(FILE_WE ${FILE} NAME_WE)
    get_source_file_property(shadertype ${FILE} ShaderType)
    add_custom_command(TARGET shaders
        COMMAND dxc.exe /nologo /Emain /T${shadertype}_6_0 $<IF:$<CONFIG:DEBUG>,/Od,/O3> /Zi /Fo ${CMAKE_BINARY_DIR}/${FILE_WE}.cso /Fd ${CMAKE_BINARY_DIR}/${FILE_WE}.pdb ${FILE}
    MAIN_DEPENDENCY ${FILE}
    COMMENT "HLSL ${FILE}"
    WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
    VERBATIM)
endforeach(FILE)

add_dependencies(${PROJECT_NAME} shaders)

这实际上设置了一个“post build”事件。如果任何一个着色器源文件改变,那么它们都会被重建。

设置输出文件的另一种方法是使用输出文件,但是这里需要一些额外的cmake逻辑,这样就可以将输出文件添加到add_libraryadd_executable中。

代码语言:javascript
运行
复制
# SOURCES variable is all the C/C++ source files in the library

# Build HLSL shaders
set_source_files_properties(VertexShader.hlsl PROPERTIES ShaderType "vs")
set_source_files_properties(PixelShader.hlsl PROPERTIES ShaderType "ps")
    
foreach(FILE VertexShader.hlsl PixelShader.hlsl)
    get_filename_component(FILE_WE ${FILE} NAME_WE)
    get_source_file_property(shadertype ${FILE} ShaderType)
    list(APPEND CSO_FILES ${CMAKE_BINARY_DIR}/${FILE_WE}.cso)
    add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/${FILE_WE}.cso
        COMMAND dxc.exe /nologo /Emain /T${shadertype}_6_0 $<IF:$<CONFIG:DEBUG>,/Od,/O3> /Zi /Fo ${CMAKE_BINARY_DIR}/${FILE_WE}.cso /Fd ${CMAKE_BINARY_DIR}/${FILE_WE}.pdb ${FILE}
    MAIN_DEPENDENCY ${FILE}
    COMMENT "HLSL ${FILE}"
    WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
    VERBATIM)
endforeach(FILE)

add_library(library2 ${SOURCES} ${CSO_FILES})

第二个版本只在源代码更改时构建特定的输出文件,但一般来说,您不需要使用着色器这种级别的粒度。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72418640

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档