# SPIR-V compiler custom\_command has unexpected execution order

**URL:** https://discourse.cmake.org/t/spir-v-compiler-custom-command-has-unexpected-execution-order/353
**Category:** Usage
**Created:** [December 11, 2019, 4:49pm UTC](https://discourse.cmake.org/t/spir-v-compiler-custom-command-has-unexpected-execution-order/353 "2019-12-11T16:49:43Z")
**Posts on this page:** 5
**Page:** 1

<div class="post-metadata">

### Author: ![Bodie](https://discourse.cmake.org/user_avatar/discourse.cmake.org/bodie/32/237_2.png) [@Bodie](https://discourse.cmake.org/u/Bodie)
#### Post date: [December 11, 2019, 4:49pm UTC](https://discourse.cmake.org/t/spir-v-compiler-custom-command-has-unexpected-execution-order/353/1 "2019-12-11T16:49:43Z")

</div>

Hi all! First post. I’ve been using CMake with C++ for a while, but have avoided custom commands and targets until now.

Here’s my CMakeLists.txt: [https://paste.ubuntu.com/p/KTMTk473qm/](https://paste.ubuntu.com/p/KTMTk473qm/)

> **Background**
>
> I have a C++ library target that depends on some generated C++ source files. A CMake `custom_command` calls a script to generate the C++ sources from compiled shaders, which themselves depend on shader source files via a `custom_command`. Each shader input file has a separate `custom_command` since I didn’t want to rebuild all shaders if any one of them changed. (Is this wrong?)
> 
> > **Custom commands**
> >
> > So, when I change a shader source file, a `custom_command` must recompile that file, and then a `custom_command` must run the generator to create the C++ source file that the shader library depends on, and then `add_library` uses this generated file.
> 
> > **I know separate directory makes it not work**
> >
> > The shaders and their CMakeLists are in a separate directory alongside the shader library.
> > 
> > This seems straightforward, but it doesn’t work – I suppose this is because the custom command must be declared in the same CMakeLists file as the target depending on its output. Is there a better way to do this?

* * *

So, I’ve created a `custom_target` which I manually build. As described in **Background** , the `custom_target` generates source files, and depends on the output of several `custom_commands`.

The unexpected behavior is that the `COMMAND` for the `custom_target` gets run **before** the `COMMAND`s for the `custom_commands` it depends on. For this reason, I always have to build it twice in order to get the correctly generated files.

In other words, line 60 (`${PHX_CLI} gen ...`) is getting run before the shaders are compiled (e.g., line 17, `${SPV_COMPILER} -V ...`), so the generated files are always from the previous version of the shaders.

For this reason, manually setting up the dependencies using `add_dependencies` causes the resulting binary to have the wrong versions of the shaders, so I’ve had to do it manually so far. I suppose I could just put it all in one giant custom target, but I was hoping not to recompile and rebuild every shader every time.

Can anyone help clarify what’s going on here?

---

<div class="post-metadata">

### Author: ![erk](https://discourse.cmake.org/user_avatar/discourse.cmake.org/erk/32/114_2.png) [@erk](https://discourse.cmake.org/u/erk)
#### Post date: [December 11, 2019, 8:31pm UTC](https://discourse.cmake.org/t/spir-v-compiler-custom-command-has-unexpected-execution-order/353/2 "2019-12-11T20:31:55Z")

</div>

Not sure why your example does not work, may be a problem with the implicit `CMAKE_CURRENT_SOURCE_DIR` location in your custom command/target.

I suggest this example which looks ok to me:  
[custom\_tgt\_cmd\_ex.zip](https://discourse.cmake.org/uploads/short-url/aSMynbC7JiFF0zRgl3FL4rfFBrO.zip) (2.5 KB)

I used a python script as “pseudo compiler”.

```
$ mkdir b
$ cd b
$ cmake ../custom_tgt_cmd_ex
-- Found Python3: /home/enoulard/VEnvs/py36torch1/bin/python3.6 (found version "3.6.6") found components: Interpreter 
-- Configuring done
-- Generating done
-- Build files have been written to: /home/enoulard/Research/CMake/b
$ make GenerateShaderResources
Scanning dependencies of target GenerateShaderResources
[20%] Compiling pushconstants.frag shader...
[40%] Compiling triangle.vert shader...
[60%] Compiling triangle.frag shader...
[80%] Compiling pushconstants.vert shader...
[100%] Generating assets ...
Reading from . writing to /home/enoulard/Research/CMake/b/dep/res
[100%] Built target GenerateShaderResources
$ touch ../custom_tgt_cmd_ex/vk_renderer_pushconstants.vert.glsl 
$ make GenerateShaderResources
[20%] Compiling pushconstants.vert shader...
[40%] Generating assets ...
Reading from . writing to /home/enoulard/Research/CMake/b/dep/res
[100%] Built target GenerateShaderResources
$ touch ../custom_tgt_cmd_ex/*triangl*glsl
$ make GenerateShaderResources
[20%] Compiling triangle.vert shader...
[40%] Compiling triangle.frag shader...
[60%] Generating assets ...
Reading from . writing to /home/enoulard/Research/CMake/b/dep/res
[100%] Built target GenerateShaderResources
$
```

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)
#### Post date: [December 12, 2019, 1:26pm UTC](https://discourse.cmake.org/t/spir-v-compiler-custom-command-has-unexpected-execution-order/353/3 "2019-12-12T13:26:14Z")

</div>

Outputs of a custom command are “attached” to a single target. (Well, they can be attached to multiple, but that doesn’t work in general for reasons related to various generators.) So in your example, I would do a hybrid of your last two bits:

```cmake
add_custom_command(
    OUTPUT
	../dep/res/res/triangle_frag_spv_decl.cxx ../dep/res/res/triangle_frag_spv_real.cxx
	../dep/res/res/triangle_vert_spv_decl.cxx ../dep/res/res/triangle_vert_spv_real.cxx
	../dep/res/res/pushconstants_frag_spv_decl.cxx ../dep/res/res/pushconstants_frag_spv_real.cxx
	../dep/res/res/pushconstants_vert_spv_decl.cxx ../dep/res/res/pushconstants_vert_spv_real.cxx
    DEPENDS
	triangle.vert.spv triangle.frag.spv
	pushconstants.vert.spv pushconstants.frag.spv
    WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
    COMMAND ${PHX_CLI} gen --skip-finalize -l 9 --from . --to ../dep/res --match ".*\.spv"
    COMMENT "Generating assets..."
)

add_custom_target(GenerateShaderResources
  DEPENDS
	../dep/res/res/triangle_frag_spv_decl.cxx ../dep/res/res/triangle_frag_spv_real.cxx
	../dep/res/res/triangle_vert_spv_decl.cxx ../dep/res/res/triangle_vert_spv_real.cxx
	../dep/res/res/pushconstants_frag_spv_decl.cxx ../dep/res/res/pushconstants_frag_spv_real.cxx
	../dep/res/res/pushconstants_vert_spv_decl.cxx ../dep/res/res/pushconstants_vert_spv_real.cxx
)

```

I would also suggest using absolute paths (based on `CMAKE_CURRENT_BINARY_DIR`) rather than relative paths. If `ninja` builds it properly then, I’d put a lot more trust into it. Visual Studio is the next “oddball” if you want to support it.

---

<div class="post-metadata">

### Author: ![Bodie](https://discourse.cmake.org/user_avatar/discourse.cmake.org/bodie/32/237_2.png) [@Bodie](https://discourse.cmake.org/u/Bodie)
#### Post date: [December 12, 2019, 5:06pm UTC](https://discourse.cmake.org/t/spir-v-compiler-custom-command-has-unexpected-execution-order/353/4 "2019-12-12T17:06:15Z")

</div>

Thanks Ben, that mostly sense except for this bit:

> [@ben.boeckel](#):
>
> I would also suggest using absolute paths _(based on `CMAKE_CURRENT_BINARY_DIR`)_

Since these sources are generated in the source tree, won’t they then be inaccessible to the target that depends on them?

* * *

Edit: So, this seems to work (I used `CMAKE_CURRENT_SOURCE_DIR`) with the manual target – and it also seems to pick up the changes in the dependent package, when I go to build it. It seems to defer the final `.cxx` source generation to just before the dependent package is built, rather than generating sources when I build the custom target. This is a big improvement over a seemingly unnecessary double-build.

Now, if I `add_dependencies(Resource GenerateShaderResources)` later, after the subdirectory containing `Resource` is added, my expectation is that the sources will be generated before `Resource` is built, but in reality a) it always runs this build (I know this is because custom targets are always stale, but I’m not sure if there’s a better approach here), and b) it _does not_ generate the `.cxx` sources the first time. Then I need to build again to get the fresh generated sources. Odd.

For example, I would expect these steps to run in opposite order (step 1 after steps 2-5): [https://paste.ubuntu.com/p/n2jkT9TjK5/](https://paste.ubuntu.com/p/n2jkT9TjK5/)

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)
#### Post date: [February 15, 2020, 11:28pm UTC](https://discourse.cmake.org/t/spir-v-compiler-custom-command-has-unexpected-execution-order/353/6 "2020-02-15T23:28:56Z")

</div>

> [@Bodie](#):
>
> b) it _does not_ generate the `.cxx` sources the first time. Then I need to build again to get the fresh generated sources. Odd.

Hmm. I would debug using the Ninja generator to see what `-t explain` is saying why it builds it the second time. I suspect there are missing dependencies somewhere in there somewhere.
