0

I've a target which has some headers in its SOURCES among others; these are generated using add_custom_command. Here's the excerpt

set(MY_SOURCES
  a.txt
  b.txt)

set(MY_HEADERS)
foreach (TXT ${MY_SOURCES})
  add_custom_command(OUTPUT ${TXT}.h
    COMMAND txt2h
    -i "${CMAKE_CURRENT_SOURCE_DIR}/${TXT}"
    -o "${TXT}.h"
    MAIN_DEPENDENCY ${TXT}
    COMMENT "Generating header from ${TXT}"
    VERBATIM)
  list(APPEND MY_HEADERS "${CMAKE_CURRENT_BINARY_DIR}/${TXT}.h")
endforeach ()

add_executable(exe main.cpp ${MY_HEADERS})
target_include_directories(exe PRIVATE ${CMAKE_CURRENT_BINARY_DIR})

This generates (cmake -B build) and builds (cmake --build build) fine.

When I edit a.txt and run cmake --build build. It regenerates a.txt.h since I see

Generating header from a.txt

However, the exe target isn't built. Since the generated header is listed as a source for exe, I'm hoping it should also make exe dirty and rebuild it. What am I missing?

I verified the timestamps on a.txt and a.txt.h match and are newer than the exe's.

References

  1. Adding a custom command and generated file (Official CMake tutorial)
  2. Generated sources in CMake builds
legends2k
  • 31,634
  • 25
  • 118
  • 222
  • Not sure it helps but [Handling header files dependencies with cmake](https://stackoverflow.com/questions/7461000/handling-header-files-dependencies-with-cmake) has some good answers. Every answer has something interesting to say regarding this. – Ted Lyngmo Dec 28 '21 at 00:17
  • 1
    And `add_executable(exe main.cpp ${MY_HEADERS})` looks wrong anyway. That will treat the headers as implementation files if I'm not mistaken. – Ted Lyngmo Dec 28 '21 at 00:18
  • 1
    I've usually seen headers listed in `add_executable`. This makes sure the executable is rebuilt when a header changes, no? Also IDEs list the headers if put there; see https://stackoverflow.com/questions/36174499/why-add-header-files-into-add-library-add-executable-command-in-cmake – legends2k Dec 28 '21 at 00:22
  • I see. Ok, that's probably the proper way to do it then. I wonder if adding the [`HEADER_FILE_ONLY`](https://cmake.org/cmake/help/latest/prop_sf/HEADER_FILE_ONLY.html#prop_sf:HEADER_FILE_ONLY) property would make a difference? – Ted Lyngmo Dec 28 '21 at 00:26
  • 2
    `However, the exe target isn't built.` In what way does "exe target" depend on the header? Does `main.cpp` include it? I.e. _what exactly_ should be rebuild and in what way when `"${TXT}.h"` changes? – KamilCuk Dec 28 '21 at 00:53
  • @KamilCuk Shouldn't `exe` be rebuilt if `main.cpp` or any of `${MY_HEADERS}` are updated (because of `add_executable(exe main.cpp ${MY_HEADERS})`)? – Ted Lyngmo Dec 28 '21 at 00:56
  • 3
    No, it should not. Executables depend on object files, object files depend on cpp files. No cpp files change -> no object files change -> no need to rebuild executable. Unless the cpp file includes the header, in which case it depends on it. Adding header files to `add_executable` only makes them show in some ide. – KamilCuk Dec 28 '21 at 01:00
  • 1
    @KamilCuk Oh, thanks. That may very well be the problem then. – Ted Lyngmo Dec 28 '21 at 01:05
  • @Kamil That indeed was the issue. Today I learned that CMake scans every C or C++ source for included headers (and the headers they include in turn) to form the dependency tree. I'm dealing with txt files which are processed differently, so I've to build this tree manually. Thanks! – legends2k Dec 28 '21 at 11:50
  • @Kamil I'd be happy to accept your answer, if you give one. – legends2k Dec 28 '21 at 11:51
  • @KamilCuk Mind writing someting up about this? – Ted Lyngmo Dec 30 '21 at 02:24

1 Answers1

2

Header files are not compiled. Executable depends on object files, which are produced from cpp files. Only when one of cpp files include the header, then it needs to be recompiled when the header changes, then the executable will be recompiled when the header changes.

Adding the header to add_executable only makes it show in some IDEs, it has no effect.

KamilCuk
  • 120,984
  • 8
  • 59
  • 111