# Ninja: Unneeded build target dependency when using add\_custom\_command to generate a cpp file

**URL:** https://discourse.cmake.org/t/ninja-unneeded-build-target-dependency-when-using-add-custom-command-to-generate-a-cpp-file/10903
**Category:** Code
**Tags:** os:windows, comp:msvc, gen:ninja
**Created:** [May 24, 2024, 5:27pm UTC](https://discourse.cmake.org/t/ninja-unneeded-build-target-dependency-when-using-add-custom-command-to-generate-a-cpp-file/10903 "2024-05-24T17:27:22Z")
**Posts on this page:** 10
**Page:** 1

<div class="post-metadata">

### Author: ![psoftware](https://discourse.cmake.org/user_avatar/discourse.cmake.org/psoftware/32/4655_2.png) [@psoftware](https://discourse.cmake.org/u/psoftware)
#### Post date: [May 24, 2024, 5:27pm UTC](https://discourse.cmake.org/t/ninja-unneeded-build-target-dependency-when-using-add-custom-command-to-generate-a-cpp-file/10903/1 "2024-05-24T17:27:22Z")

</div>

Hi there!  
I am struggling in removing a compile dependency in my project that makes use of `add_custom_command`.

Consider this simple snippet:

```auto
cmake_minimum_required(VERSION 3.12)
project(test-cmake-customcommand-dependency VERSION 0.1.0)

add_custom_command(
    OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/resource.cpp
    COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/resource.xml ${CMAKE_CURRENT_BINARY_DIR}/resource.cpp
    MAIN_DEPENDENCY ${CMAKE_CURRENT_SOURCE_DIR}/resource.xml
    VERBATIM
    DEPENDS_EXPLICIT_ONLY
)

add_executable(test-cmake-customcommand-dependency
    main.cpp
    ${CMAKE_CURRENT_BINARY_DIR}/resource.cpp
)

```

In the project dir there is the _main.cpp_ file and a _resource.xml_ file which contains some source code. I am already using `DEPENDS_EXPLICIT_ONLY` to minimize the set of dependencies.

The custom command transforms the resource file into a cpp file, which is added to the executable source list.  
My expectation about the building steps is that the custom command execution together with resource.cpp build step can happen in parallel w.r.t the building of other source files (in this case only main.cpp). However, it seems that there is an additional resource.cpp dependency added to the building step of main.cpp, which prevents this parallelization (on cmake 3.29.3 and trunk).

By generating the Ninja graph output, we can see an order only dependency that is connected to all target sources (main.cpp, resouces.cpp2) build steps, which should not be necessary in our case. We just want a link dependency to the object file of resource.cpp, which is correctly generated.

 ![graph3](https://discourse.cmake.org/uploads/default/original/2X/b/be5c611419ce68f99b68b0ddc3e69ea3773f83ec.png)

Setting Policy CMP0154 and an empty file set for the executable target does not seem to solve the issue, as it moves the dependency to the cmake order only private group.

We checked the CMake project source code and it seems that the addition of this dependency cannot be prevented (in `cmNinjaTargetGenerator::WriteObjectBuildStatements`, _ccout_ and _orderOnlyDeps_), unless our file is a cxxmodule and specified in the file set.

Am I missing anything? Is there any way to solve this issue?

Thank you a lot for your help!

Best regards

---

<div class="post-metadata">

### Author: ![psoftware](https://discourse.cmake.org/user_avatar/discourse.cmake.org/psoftware/32/4655_2.png) [@psoftware](https://discourse.cmake.org/u/psoftware)
#### Post date: [June 4, 2024, 1:20pm UTC](https://discourse.cmake.org/t/ninja-unneeded-build-target-dependency-when-using-add-custom-command-to-generate-a-cpp-file/10903/2 "2024-06-04T13:20:11Z")

</div>

Is there someone that can help me with this?  
Should I report this as an issue on the CMake Gitlab?

Thank you (:

---

<div class="post-metadata">

### Author: ![craig.scott](https://discourse.cmake.org/user_avatar/discourse.cmake.org/craig.scott/32/20_2.png) [@craig.scott](https://discourse.cmake.org/u/craig.scott)
#### Post date: [June 4, 2024, 9:36pm UTC](https://discourse.cmake.org/t/ninja-unneeded-build-target-dependency-when-using-add-custom-command-to-generate-a-cpp-file/10903/3 "2024-06-04T21:36:04Z")

</div>

Do you see the same behavior with CMake 3.27 or older?

@ben.boeckel Some of the comments suggest that there may have been a regression with some of the C++20 modules work, but let’s see what the response to my question just above is first before we conclude anything there.

---

<div class="post-metadata">

### Author: ![psoftware](https://discourse.cmake.org/user_avatar/discourse.cmake.org/psoftware/32/4655_2.png) [@psoftware](https://discourse.cmake.org/u/psoftware)
#### Post date: [June 5, 2024, 2:10am UTC](https://discourse.cmake.org/t/ninja-unneeded-build-target-dependency-when-using-add-custom-command-to-generate-a-cpp-file/10903/4 "2024-06-05T02:10:32Z")

</div>

Hi mr. Craig, thank you for you time!

I think I can only check it on CMake 3.27 because that’s the minimum version that supports `DEPENDS_EXPLICIT_ONLY`, without which there would be still a global dependency on the custom command dependencies.

Sadly, testing it with CMake 3.27.1 seems to held the same result:

 ![graph-3.27](https://discourse.cmake.org/uploads/default/original/2X/e/eafa5c9ff22a3a22cde7981a1c678dc3b7366553.png)

This is the command I launched, just to double check that I used the right version CMake version (which I built from the sources, tag v3.27.1):

```bat
> "D:\src\CMake\build-3.27\bin\cmake.exe" --version
cmake version 3.27.1

> "D:\src\CMake\build-3.27\bin\cmake.exe" -B build-3.27 -GNinja -DCMAKE_BUILD_TYPE=RelWithDebInfo
> ninja -C build-3.27 -t graph | D:\tools\Graphviz-11.0.0-win64\bin\dot.exe -Tpng -ograph-3.27.png

```

Let me know if I can help with any other tests.

Kind regards

---

<div class="post-metadata">

### Author: ![craig.scott](https://discourse.cmake.org/user_avatar/discourse.cmake.org/craig.scott/32/20_2.png) [@craig.scott](https://discourse.cmake.org/u/craig.scott)
#### Post date: [June 5, 2024, 12:11pm UTC](https://discourse.cmake.org/t/ninja-unneeded-build-target-dependency-when-using-add-custom-command-to-generate-a-cpp-file/10903/5 "2024-06-05T12:11:54Z")

</div>

@ben.boeckel is probably more familiar with the dependency handling code around this, so I’ll defer to him to make the initial response for this.

---

<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: [June 8, 2024, 2:41am UTC](https://discourse.cmake.org/t/ninja-unneeded-build-target-dependency-when-using-add-custom-command-to-generate-a-cpp-file/10903/6 "2024-06-08T02:41:25Z")

</div>

This is a known (to me at least) limitation that I discovered while implementing C++ modules. [This MR](https://gitlab.kitware.com/cmake/cmake/-/merge_requests/8904) (that I plan to get back to some day; [tracking/discussion issue](https://gitlab.kitware.com/cmake/cmake/-/issues/25370)) would fix it. Basically, because we currently have a grabbag list of sources, CMake has no idea that `main.cpp` doesn’t `#include "resource.cpp"` for some reason. By making a `FILE_SET` that contains sources that we _know_ cannot be `#include`d (like C++ module interfaces are as `export module` cannot hide behind an `#include`), we can drop the dependency of other sources in the target on the generated source.

---

<div class="post-metadata">

### Author: ![psoftware](https://discourse.cmake.org/user_avatar/discourse.cmake.org/psoftware/32/4655_2.png) [@psoftware](https://discourse.cmake.org/u/psoftware)
#### Post date: [June 10, 2024, 9:48am UTC](https://discourse.cmake.org/t/ninja-unneeded-build-target-dependency-when-using-add-custom-command-to-generate-a-cpp-file/10903/7 "2024-06-10T09:48:06Z")

</div>

Hi mr. Ben, thank you for your answer!

I am glad to know this is a known issue. While trying the new FILE\_SET functionality I was wandering why there was not a way to also put options on cpp files too.

I have been reading the issue you linked and it seems that for now there are still some design issue to solve. Just to understand the issue better, I was wondering: if a cpp file is included through an include directive, isn’t the dependency automatically detected by querying the compiler? If yes, why there is the need of a global dependency on the generated files?

Also, the issue of solving this through FILE\_SET(s) properties seems to be that it does not allow to configure this behavior per target, but only per file: can’t we change the default behavior so that if a generated file is in the list of target source files, we drop the global order-only dependency at least for that target? Is there any other edge case to cover?

Our use case is really simple, we just need to embed some resources in the code in form of big arrays. The conversion from original files to cpp/h is done through a custom command. Generated cpp files are added to the target source list, then compiled. Right now, the building of _any_ target source file is not allowed until all files have been generated, reducing the potential for parallelization.

Thank you a lot!

Kind regards,

---

<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: [June 10, 2024, 11:50am UTC](https://discourse.cmake.org/t/ninja-unneeded-build-target-dependency-when-using-add-custom-command-to-generate-a-cpp-file/10903/8 "2024-06-10T11:50:30Z")

</div>

> [@psoftware](#):
>
> I was wondering: if a cpp file is included through an include directive, isn’t the dependency automatically detected by querying the compiler? If yes, why there is the need of a global dependency on the generated files?

Scenario: what is the expected behavior when compiling a source that includes it before the source exists? How is CMake supposed to know that ahead of time?

Basically, CMake ensures anything that _could_ be included is there before compiling potential includers. The compiler detection will mention it and cause recompilation if it _changes_ if it is included, but the only way to handle a new `#include` line is to have it there in the first place.

> [@psoftware](#):
>
> Also, the issue of solving this through FILE\_SET(s) properties seems to be that it does not allow to configure this behavior per target, but only per file: can’t we change the default behavior so that if a generated file is in the list of target source files, we drop the global order-only dependency at least for that target? Is there any other edge case to cover?

A policy could be made…but how to detect it? I suspect it is a policy that cannot warn, so when the policy is set to `NEW`, projects can start to get non-deterministic build failures based on build tool scheduling. I’m afraid that it’s better to have to inform CMake of this explicitly in some manner (`FILE_SET` is the most natural, but perhaps a target property could suffice).

---

<div class="post-metadata">

### Author: ![psoftware](https://discourse.cmake.org/user_avatar/discourse.cmake.org/psoftware/32/4655_2.png) [@psoftware](https://discourse.cmake.org/u/psoftware)
#### Post date: [June 10, 2024, 3:35pm UTC](https://discourse.cmake.org/t/ninja-unneeded-build-target-dependency-when-using-add-custom-command-to-generate-a-cpp-file/10903/9 "2024-06-10T15:35:02Z")

</div>

> [@ben.boeckel](#):
>
> Scenario: what is the expected behavior when compiling a source that includes it before the source exists? How is CMake supposed to know that ahead of time?
> 
> Basically, CMake ensures anything that _could_ be included is there before compiling potential includers. The compiler detection will mention it and cause recompilation if it _changes_ if it is included, but the only way to handle a new `#include` line is to have it there in the first place.

I understand now. Basically if the generated file does not exist, than asking the compiler to deduce the header dependencies will fail, because the compiler is not able to determine the path to the dependency, considering that it could come from any of the include paths. Also, the file itself could include more dependencies, which would require it to be generated before the build step. Even if we generate some empty placeholder files for the files which have the GENERATED property in the expected paths, that would not be enough. Am I right?

> [@ben.boeckel](#):
>
> A policy could be made…but how to detect it? I suspect it is a policy that cannot warn, so when the policy is set to `NEW`, projects can start to get non-deterministic build failures based on build tool scheduling.

I understand your concern, even if having a _source_ file which is both included and compiled by the same target seems apparently unusual.

> [@ben.boeckel](#):
>
> I’m afraid that it’s better to have to inform CMake of this explicitly in some manner (`FILE_SET` is the most natural, but perhaps a target property could suffice).

Do you mean like a target property which holds a list of files that are supposed to not be included?

If I can contribute also to write some code, I will be glad to help.

Best regards

---

<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: [June 10, 2024, 4:55pm UTC](https://discourse.cmake.org/t/ninja-unneeded-build-target-dependency-when-using-add-custom-command-to-generate-a-cpp-file/10903/10 "2024-06-10T16:55:04Z")

</div>

> [@psoftware](#):
>
> Even if we generate some empty placeholder files for the files which have the GENERATED property in the expected paths, that would not be enough. Am I right?

Right.

> [@psoftware](#):
>
> I understand your concern, even if having a _source_ file which is both included and compiled by the same target seems apparently unusual.

Unusual, yes, but not impossible:

```cpp
#define some_control_variable
#include "impl.cpp"

```

where `impl.cpp` on its own is “useful” as well.

> [@psoftware](#):
>
> Do you mean like a target property which holds a list of files that are supposed to not be included?

It’d be a target property that says “all generated sources with a defined `LANGUAGE` property (headers wouldn’t have one applied) are not needed for compilation of any other TU in the target”, not a list of sources. Per-source properties would be possible too, but sounds tedious to bridge.
