I have certain files (.hlsl) in one of my targets that are compiled using a custom compiler (glslc). After compilation, I use a different tool to embed the compiled binary in a c-file containing c-array like described here.
This workflow is summarized in the following code which invokes 2 custom commands:
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()
I then define a custom target that that generates the said files whenever it is built.
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)
The main issue is that the custom target build process is triggered every time I build my project regardless of the fact the none of the .hlsl files are changed. This is undesirable, I want my custom command to work just like when compiling regular .c or cpp files. They are compiled only when changed.
My requirements are as follows:
- Each time one of the .hlsl files are changed, the custom command should trigger.
- The custom command should not get triggered whenever I build the target / project.
So how can this achieved?
I tried several methods like using DEPENDS, MAIN_DEPENDENCY or using OUTPUT instead of TARGET. None worked. I also tried the solution offered here and here. They all suffer from the same issue.
As requested in the comments, Here is my attempt to use OUTPUT instead of TARGET:
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()
add_custom_commandwithOUTPUTinstead ofTARGET. Please, show you attempt when use given command flow.${shader_file}file and produce the very same file. OUTPUT denotes files which are created by the COMMAND, DEPENDS denotes files which are required by the COMMAND because it uses them.add_custom_command? Is this file actually created after executing the command? (That is, after building your project first time you could check whether OUTPUT file exists). Note, that relative path specified in OUTPUT is interpreted relative to the build directory, not relative to the source one.