1

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:

einpoklum
  • 118,144
  • 57
  • 340
  • 684
François Beaune
  • 4,270
  • 7
  • 41
  • 65
  • I expect the second command to have a `DEPENDS`, too. It should depend on some output from the first command. You have to figure out, why the first command is always build. Why do you use MAIN_DEPENDENCY? Why has one argument of DEPENDS quotatiosmarks? – usr1234567 Dec 02 '16 at 10:51
  • oslc is an executable, right? You should not depend on it, you should check it (FindOslc or similar) and then wrap the whole add_custom_command in a OSCL_FOUND. – usr1234567 Dec 02 '16 at 10:52
  • @usr1234567 The second command has no `DEPENDS` because it doesn't depend on anything. It just needs to be run when the output (the `oslc` compiler) is missing. It is wrapped in quotes because the full path to `oslc` might contain spaces on Windows. – François Beaune Dec 02 '16 at 10:57
  • `It seems that this behavior is specific to Windows.` - Under *which generator* (Visual Studio, NMake) you have observed this behaviour? Just a guess: the build tool, corresponded to this generator, doesn't understand commands without dependencies and treats them like a CMake *target* (which is always built). Adding `DEPENDS ${OSL_COMPILER}` into the second command should help with that. (Instead of `${OSL_COMPILER}` may be any source file which is never modified). – Tsyvarev Dec 02 '16 at 11:42
  • @Tsyvarev This behavior is observed with the `Visual Studio 14 2015 Win64` generator. I'll try your suggestion and report back here. Thanks! – François Beaune Dec 02 '16 at 12:47
  • @Tsyvarev Unfortunately it doesn't seem to work. – François Beaune Dec 02 '16 at 12:52
  • Have you tried quoting the paths properly (e.g. `"${PROJECT_SOURCE_DIR}/sandbox/bin/oslc"`)? – sakra Dec 02 '16 at 13:31
  • @sakra Yes, I've tried that. I think that this question is similar to mine, and the conclusion is basically that what I'm trying to achieve isn't possible with CMake. – François Beaune Dec 02 '16 at 15:11

1 Answers1

0

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.

François Beaune
  • 4,270
  • 7
  • 41
  • 65