Search code examples
cmakecmake-custom-command

add_custom_command depending on another add_custom_command


We have two add_custom_command clauses, where one depends on the other:

  1. The first command compiles an .osl source file into an .oso object file using the oslc compiler:

    set (oslc ${PROJECT_SOURCE_DIR}/sandbox/bin/oslc)
    
    add_custom_command (
        OUTPUT "${oso_dir}/${oso_filename}"
        COMMAND ${CMAKE_COMMAND} -E make_directory "${oso_dir}"
        COMMAND "${oslc}" -I"${osl_include_path}" -o "${oso_dir}/${oso_filename}" "${osl_src_abs}"
        MAIN_DEPENDENCY ${osl_src_abs}
        DEPENDS ${${headers}} ${osl_src_abs} "${oslc}"
    )
    

    Notice the dependency on ${oslc}: we explicitly depend on ${oslc} because we need to make sure it exists before we can execute this command.

  2. The second command "builds" (really, deploys) the oslc compiler by copying it from somewhere else:

    add_custom_command (
        OUTPUT "${PROJECT_SOURCE_DIR}/sandbox/bin/oslc"
        COMMAND ${CMAKE_COMMAND} -E copy ${OSL_COMPILER} ${PROJECT_SOURCE_DIR}/sandbox/bin/
    )
    

While this setup works, it has the side effect that both commands are always executed (the second command followed by the first command) even when the .osl input file hasn't been modified.

It seems that this behavior is specific to Windows. It appears to work fine on Linux.

If the dependency to ${oslc} is removed from the first command, the second command is no longer executed at all, even when the oslc compiler is missing; but on the other hand, .osl files are now only recompiled when they have changed since the last build, as desired (as long as oslc is present).

Is there anything wrong with this setup? If not, what is the right way to combine both features: compiling .osl files only when they have changed since the last build, and "building" the oslc compiler (required by the first step) when it doesn't yet exist?

The actual CMake script is available on GitHub:


Solution

  • A simple solution, at least for Windows, is to change the second command to

    add_custom_command (
        TARGET appleseed.shaders
        PRE_BUILD
        COMMAND ${CMAKE_COMMAND} -E copy ${OSL_COMPILER} ${PROJECT_SOURCE_DIR}/sandbox/bin/
    )
    

    (notice the PRE_BUILD keyword)

    and to remove the explicit dependency to ${oslc} from the first command.