What is the ideal way to handle custom file type dependencies in CMake?

Viewed 288

I'm working on a C++ project where I'm encountering an issue I've also had in the past. Alongside my actual executable, I have shader files that need to be compiled.

Ideally, a file called hello.vert in the source directory would be compiled at build-time to hello.vert.spv in my build output directory.

My Attempt

My current implementation does not work - it seems the output files are not created, and if I replace the COMMAND with something like "echo hi", touch the source files and then build, it does not show any output either. This is essentially what I have created:

add_executable(test test.cpp)

function(build_shader TARGETOBJ SHADERNAME)
    set(FILENAME "${CMAKE_SOURCE_DIR}/${SHADERNAME}")
    set(OUTNAME "${CMAKE_BINARY_DIR}/${SHADERNAME}.spv")
    add_custom_command(OUTPUT ${OUTNAME}
        COMMAND glslc ${FILENAME} -o ${OUTNAME})
    add_custom_target(MAKE_${SHADERNAME} ALL DEPENDS ${FILENAME})
    add_dependencies(${TARGETOBJ} MAKE_${SHADERNAME})
endfunction()

build_shader(test hello.vert)
build_shader(test hello.frag)

In An Ideal World

In plain makefiles, my solution would look like this:

test: hello.vert.spv hello.frag.spv
    ...

%.spv: %
    glslc $< -o $@

In CMake, I haven't been able to find a way to handle certain filetypes in a custom way - this would make the solution as easy as:

add_executable(test test.cpp hello.vert hello.frag)

Is there a sane, reliable way to do this sort of thing?

1 Answers

You meant to:

function(build_shader TARGETOBJ SHADERNAME)
    set(FILENAME "${CMAKE_SOURCE_DIR}/${SHADERNAME}")
    set(OUTNAME "${CMAKE_BINARY_DIR}/${SHADERNAME}.spv")
    add_custom_command(OUTPUT ${OUTNAME}
        COMMAND glslc ${FILENAME} -o ${OUTNAME}
        DEPENDS ${FILENAME})
    add_custom_target(MAKE_${SHADERNAME} ALL DEPENDS ${OUTNAME})
    add_dependencies(${TARGETOBJ} MAKE_${SHADERNAME})
endfunction()

The target depends on OUTNAME. OUTNAME depends on FILENAME.

Related