# Trying to generate header file using add\_custom\_command, resulted limping build

**URL:** https://discourse.cmake.org/t/trying-to-generate-header-file-using-add-custom-command-resulted-limping-build/6621
**Category:** Code
**Tags:** os:windows, gen:ninja
**Created:** [October 6, 2022, 4:05pm UTC](https://discourse.cmake.org/t/trying-to-generate-header-file-using-add-custom-command-resulted-limping-build/6621 "2022-10-06T16:05:55Z")
**Posts on this page:** 7
**Page:** 1

<div class="post-metadata">

### Author: ![hihig2001](https://discourse.cmake.org/user_avatar/discourse.cmake.org/hihig2001/32/2815_2.png) [@hihig2001](https://discourse.cmake.org/u/hihig2001)
#### Post date: [October 6, 2022, 4:05pm UTC](https://discourse.cmake.org/t/trying-to-generate-header-file-using-add-custom-command-resulted-limping-build/6621/1 "2022-10-06T16:05:55Z")

</div>

Hi, I’m trying to generate a header file during build.  
When I changed the template file(DataTableSchema.h) and try build, ninja only executes custom command and not build a library.  
and next time I command build with ninja, ninja detects that generated header file(datatable.hpp) has been modified,  
so a library file(lib.cpp) that including it recompiled.

I googled about it a lot, but it seems unusual for people.  
[https://gitlab.kitware.com/cmake/community/-/wikis/FAQ#how-can-i-generate-a-source-file-during-the-build](https://gitlab.kitware.com/cmake/community/-/wikis/FAQ#how-can-i-generate-a-source-file-during-the-build)  
all the explanation tells me that they don’t seems experiencing the issue.  
and it seems ‘touch’ is necessary to pick ‘depends’ option is it supposed to be necessary?

I’m using cmake with visual studio 2022 integrated environment.

- VS2022 17.3.4 (i tried with commandline too so i guess it wouldn’t be matter though)
- cmake version 3.23.22060601-MSVC\_2
- ninja version 1.10.2

Game/knuckles/CMakeLists.txt

```auto
add_custom_command(
    COMMAND "py" "${CMAKE_SOURCE_DIR}/../Tools/CodeGenerator/main.py" 
            "-i" "${CMAKE_SOURCE_DIR}/../UnrealApp/Source/Knuckles/GameData/DataTableSchema.h"
            "-o" "${CMAKE_CURRENT_SOURCE_DIR}/include/Knuckles/_generated/datatable.hpp"
    COMMAND cmake -E touch "./include/Knuckles/_generated/datatable.hpp" #without this line depends is not working and custom command runs everytime when we build
    DEPENDS "${CMAKE_SOURCE_DIR}/../UnrealApp/Source/Knuckles/GameData/DataTableSchema.h"
    OUTPUT "./include/Knuckles/_generated/datatable.hpp"
    COMMENT "Generating code for datatable."
)

add_library(knuckles_lib "./src/lib.cpp" "./include/Knuckles/_generated/datatable.hpp")

# Includes
set(knuckles_lib_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/include"
    CACHE STRING "")
target_include_directories(knuckles_lib PUBLIC "$<BUILD_INTERFACE:${knuckles_lib_INCLUDE_DIR}>"
                                         "$<INSTALL_INTERFACE:./${CMAKE_INSTALL_INCLUDEDIR}>")

#I tried wrapping target trick too but it has no difference
#add_library(knuckles_lib "./src/lib.cpp")
#add_custom_target(run_codegen DEPENDS "./include/Knuckles/_generated/datatable.hpp")
#add_dependencies(knuckles_lib run_codegen)

```

also it seems that directory structure does matters?

```auto
Game
   - console_app //executable
       - src
       - CMakeLists.txt //build process usually starts with building the executable
   - knuckles //lib
       - include/knuckles/_generated //generated header files goes here
       - src
       - CMakeLists.txt //codegen implemented here
   - CMakeLists.txt //main cmake

```

Game/kunckles/src/lib.cpp

```auto
#include "knuckles/_generated/datatable.hpp"
//below code

```

---

<div class="post-metadata">

### Author: ![hihig2001](https://discourse.cmake.org/user_avatar/discourse.cmake.org/hihig2001/32/2815_2.png) [@hihig2001](https://discourse.cmake.org/u/hihig2001)
#### Post date: [October 7, 2022, 7:13am UTC](https://discourse.cmake.org/t/trying-to-generate-header-file-using-add-custom-command-resulted-limping-build/6621/2 "2022-10-07T07:13:56Z")

</div>

Solved problem by chaning path explicitly!  
I don’t understand what makes this kind of difference…  
Please someone explains me, necessary of touch and explicit path!

worked example.

```auto
add_custom_command(
    COMMAND "py" "${CMAKE_SOURCE_DIR}/../Tools/CodeGenerator/main.py" 
            "-i" "${CMAKE_SOURCE_DIR}/../UnrealApp/Source/Knuckles/GameData/DataTableSchema.h"
            "-o" "${CMAKE_CURRENT_SOURCE_DIR}/include/Knuckles/_generated/datatable.hpp"
    COMMAND ${CMAKE_COMMAND} -E touch "${CMAKE_CURRENT_SOURCE_DIR}/include/Knuckles/_generated/datatable.hpp" #without this line depends is not working and custom command runs everytime when we build
    DEPENDS "${CMAKE_SOURCE_DIR}/../UnrealApp/Source/Knuckles/GameData/DataTableSchema.h"
    OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/include/Knuckles/_generated/datatable.hpp"
    COMMENT "Generating code for datatable."
)

add_library(knuckles_lib "./src/lib.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/include/Knuckles/_generated/datatable.hpp")

```

---

<div class="post-metadata">

### Author: ![hsattler](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/h/59ef9b/32.png) [@hsattler](https://discourse.cmake.org/u/hsattler)
#### Post date: [October 7, 2022, 9:37am UTC](https://discourse.cmake.org/t/trying-to-generate-header-file-using-add-custom-command-resulted-limping-build/6621/3 "2022-10-07T09:37:56Z")

</div>

You should generate the file in the build directory and not in the source directory.

It runs each time because the two file paths don’t match.

---

<div class="post-metadata">

### Author: ![hihig2001](https://discourse.cmake.org/user_avatar/discourse.cmake.org/hihig2001/32/2815_2.png) [@hihig2001](https://discourse.cmake.org/u/hihig2001)
#### Post date: [October 7, 2022, 10:46am UTC](https://discourse.cmake.org/t/trying-to-generate-header-file-using-add-custom-command-resulted-limping-build/6621/4 "2022-10-07T10:46:58Z")

</div>

Could you explain bit more persicely? because before scripts already didn’t generate the header file in every time after I add touch command. but the problem was ninja didn’t catch dependency I think.

It was like that

1. if no touch on the template file, ninja doesn’t do nothing
2. if the template file has modified, when I build, ninja runs custom command and generate the header file, but source code that including header file didn’t catch change of header file. so ninja don’t do any compiling.
3. so after 2, if I try build again, ninja now catches change of header file and build the source code.

I thought that ‘.’ in path represent the current path of that 'CMakeLists.txt". but I guess ninja sees it differently? And somehow changing ‘.’ to the absolute path convince ninja somehow.

---

<div class="post-metadata">

### Author: ![hsattler](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/h/59ef9b/32.png) [@hsattler](https://discourse.cmake.org/u/hsattler)
#### Post date: [October 7, 2022, 11:58am UTC](https://discourse.cmake.org/t/trying-to-generate-header-file-using-add-custom-command-resulted-limping-build/6621/5 "2022-10-07T11:58:04Z")

</div>

First, you should try to keep the source directory clean of build artifacts. This allows to have more than one build tree.

Second, the add\_custom\_command documentation states for OUTPUT that relative path is interpreted relative to current build directory but your command creates in the current source directory. As the specified output file never exists, the rule is executed every time.

The touch command is only needed because your python command does not update the time stamp if it does not create the file with possibly same content. For ninja generator you can alternatively use the BYPRODUCT statement. Then you can use a dummy stamp file as output, the actual output file as byproduct and the file does not change and the compiler does not need to recompile it.

---

<div class="post-metadata">

### Author: ![hihig2001](https://discourse.cmake.org/user_avatar/discourse.cmake.org/hihig2001/32/2815_2.png) [@hihig2001](https://discourse.cmake.org/u/hihig2001)
#### Post date: [October 11, 2022, 3:52am UTC](https://discourse.cmake.org/t/trying-to-generate-header-file-using-add-custom-command-resulted-limping-build/6621/6 "2022-10-11T03:52:43Z")

</div>

Thanks a lot, I now understand what happens with my previous code! 😃

I thought that relative path, ‘./path’, in ‘.’ represents current cmake path, but it turns out it could be different per command!

I have following question based on your answer.

1. generating different file based on build tree sounds nice! but my original intention that putting generating code in ‘include’ directory was,  
(a) I wanted to be in same path(include/knuckles/\_generated) when I do install  
(b) I wanted include path won’t changed in my source code  
Is there are solution for that?

2. I tried with BYPRODUCT stamp technique you mentioned based on answer of below link  
[ninja - CMake's add\_custom\_command doesnt trigger rebuild of library - Stack Overflow](https://stackoverflow.com/questions/65307005/cmakes-add-custom-command-doesnt-trigger-rebuild-of-library)  
but pitfall I found is that It is not working if generated file is not pre-existed. Is there are better ways to do that?

---

<div class="post-metadata">

### Author: ![hihig2001](https://discourse.cmake.org/user_avatar/discourse.cmake.org/hihig2001/32/2815_2.png) [@hihig2001](https://discourse.cmake.org/u/hihig2001)
#### Post date: [October 11, 2022, 7:15am UTC](https://discourse.cmake.org/t/trying-to-generate-header-file-using-add-custom-command-resulted-limping-build/6621/7 "2022-10-11T07:15:34Z")

</div>

I found solution for first following question my self, would you think this is correct approach?

```auto
file(GLOB_RECURSE codegen_scripts "${CMAKE_SOURCE_DIR}/../Tools/CodeGenerator/*.py")
add_custom_command(
    COMMAND "py" "${CMAKE_SOURCE_DIR}/../Tools/CodeGenerator/main.py" 
            "-i" "${CMAKE_SOURCE_DIR}/../UnrealApp/Source/Knuckles/GameData/DataTableSchema.h"
            "-o" "${CMAKE_BINARY_DIR}/include/knuckles/_generated/datatable.hpp"
    DEPENDS ${codegen_scripts}
    MAIN_DEPENDENCY "${CMAKE_SOURCE_DIR}/../UnrealApp/Source/Knuckles/GameData/DataTableSchema.h"
    OUTPUT "${CMAKE_BINARY_DIR}/include/knuckles/_generated/datatable.hpp"
    COMMENT "Generating code for datatable."
) #1. CHANGE CMAKE_SOURCE_DIR => CMAKE_BINARY_DIR

# Consturct
add_library(knuckles_lib "./src/lib.cpp" "${CMAKE_BINARY_DIR}/include/knuckles/_generated/datatable.hpp")

# Includes
set(knuckles_lib_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/include" CACHE STRING "")
set(knuckles_lib_GEN_INCLUDE_DIR "${CMAKE_BINARY_DIR}/include" CACHE STRING "")
target_include_directories(knuckles_lib PUBLIC "$<BUILD_INTERFACE:${knuckles_lib_INCLUDE_DIR};${knuckles_lib_GEN_INCLUDE_DIR}>"
                                               "$<INSTALL_INTERFACE:./${CMAKE_INSTALL_INCLUDEDIR}>")

```

[Main]CMakeLists.txt

```auto
install(DIRECTORY ${knuckles_lib_INCLUDE_DIR} DESTINATION "./")
install(DIRECTORY ${knuckles_lib_GEN_INCLUDE_DIR} DESTINATION "./")

```
