I use this pattern for CMake shaders that works with both Ninja and the MSVC generators.
I assume your target name is ${PROJECT_NAME} below.
DirectX 11
# Build HLSL shaders
set(HLSL_SHADER_FILES VertexShader.hlsl PixelShader.hlsl)
set_source_files_properties(VertexShader.hlsl PROPERTIES ShaderType "vs")
set_source_files_properties(PixelShader.hlsl PROPERTIES ShaderType "ps")
set_source_files_properties(${HLSL_SHADER_FILES} PROPERTIES ShaderModel "4_0")
foreach(FILE ${HLSL_SHADER_FILES})
get_filename_component(FILE_WE ${FILE} NAME_WE)
list(APPEND CSO_SHADER_FILES ${CMAKE_BINARY_DIR}/${FILE_WE}.cso)
get_source_file_property(shadertype ${FILE} ShaderType)
get_source_file_property(shadermodel ${FILE} ShaderModel)
add_custom_command(TARGET ${PROJECT_NAME} PRE_LINK
COMMAND fxc.exe /nologo /Emain /T${shadertype}_${shadermodel} $<IF:$<CONFIG:DEBUG>,/Od,/O1> /Zi /Fo ${CMAKE_BINARY_DIR}/${FILE_WE}.cso /Fd ${CMAKE_BINARY_DIR}/${FILE_WE}.pdb ${FILE}
COMMENT "HLSL ${FILE}"
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
VERBATIM)
endforeach(FILE)
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy ${CSO_SHADER_FILES} $<TARGET_FILE_DIR:${PROJECT_NAME}>
COMMAND_EXPAND_LISTS)
I use this in my DirectX Tool Kit tutorials. You can also see the rest of the CMake on directx-vs-templates.|
DirectX 12
# Build HLSL shaders
set(HLSL_SHADER_FILES VertexShader.hlsl PixelShader.hlsl)
set_source_files_properties(VertexShader.hlsl PROPERTIES ShaderType "vs")
set_source_files_properties(PixelShader.hlsl PROPERTIES ShaderType "ps")
foreach(FILE ${HLSL_SHADER_FILES})
get_filename_component(FILE_WE ${FILE} NAME_WE)
list(APPEND CSO_SHADER_FILES ${CMAKE_BINARY_DIR}/${FILE_WE}.cso)
get_source_file_property(shadertype ${FILE} ShaderType)
add_custom_command(TARGET ${PROJECT_NAME} PRE_LINK
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}
COMMENT "HLSL ${FILE}"
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
VERBATIM)
endforeach(FILE)
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy ${CSO_SHADER_FILES} $<TARGET_FILE_DIR:${PROJECT_NAME}>
COMMAND_EXPAND_LISTS)
I use this in my DirectX Tool Kit tutorials. You can also see the rest of the CMake on directx-vs-templates.|
UPDATED: I updated this for a CMake 3.31 deprecation (CMP0175), added logic to ensure the .cso files are copied into the bin folder, and added the DX12 equivalent.
.hlslfiles among source files foradd_executablecall. Visual Studio will automatically compile them.