1

I have in my CMakeLists.txt:

add_custom_command(OUTPUT chattr.tab.cpp
  DEPENDS table_gen
  COMMAND ./table_gen > chattr.tab.cpp
)

This puts the generated source file chattr.tab.cpp in the object directory (which is as I want it). However, as a result a #include "someheader.h" inside chattr.tab.cpp doesn't find that header, which is in the source directory.

This generated file is only added to some targets. Is there a way to cause some include directory to be added when compiling this generated source file (to CMakeFiles/sometarget.dir/chattr.tab.cpp.o), and only when compiling that source file? As opposed to adding the include directory to all targets that use it? The latter would require to add multiple target_include_directories() and would cause the include to be used for every source file of that target, not just the generated source file.

EDIT:

As per squareskittles answer, I produced the following CMakeLists.txt file (only showing the bottom part):

....
#=================================================================
# GENERATED SOURCE FILES
#

add_executable(table_gen table_gen.cxx)

add_custom_command(OUTPUT chattr.tab.cpp
  DEPENDS table_gen
  COMMAND ./table_gen > chattr.tab.cpp
)

add_custom_command(OUTPUT PgnGrammar.h
  DEPENDS generate_PgnGrammar.h.sh
  COMMAND ${CMAKE_CURRENT_LIST_DIR}/generate_PgnGrammar.h.sh
)

set(GENERATED_SOURCES chattr.tab.cpp PgnGrammar.h)

set_source_files_properties(chattr.tab.cpp PROPERTIES
  INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}"  # For local header files.
)

#=================================================================
# TEST EXECUTABLES
#

add_executable(tstchessposition tstchessposition.cxx)
target_link_libraries(tstchessposition PRIVATE AICxx::cwchessboard AICxx::cwds)

add_executable(tstbenchmark tstbenchmark.cxx)
target_link_libraries(tstbenchmark PRIVATE AICxx::cwchessboard AICxx::cwds)

add_executable(tstpgnread tstpgnread.cxx PgnDatabase.cxx MemoryBlockList.cxx ${GENERATED_SOURCES})
target_link_libraries(tstpgnread PRIVATE AICxx::cwchessboard AICxx::cwds)

add_executable(tsticonv tsticonv.cxx)
target_link_libraries(tsticonv PRIVATE PkgConfig::glibmm)

add_executable(tstpgn tstpgn.cxx PgnDatabase.cxx MemoryBlockList.cxx ${GENERATED_SOURCES})
target_link_libraries(tstpgn PRIVATE AICxx::cwchessboard AICxx::cwds)

add_executable(tstspirit tstspirit.cxx PgnGrammar.h)
target_include_directories(tstspirit PUBLIC "${top_objdir}")

But this results in:

[ 51%] Generating chattr.tab.cpp
./table_gen > chattr.tab.cpp
[ 54%] Generating chattr.tab.cpp
./table_gen > chattr.tab.cpp

Apparently, because both, tstpgnread and tstpgn link with chattr.tab.cpp, it is generated TWICE?! Is this a bug in CMake or am I doing something else wrong?

Carlo Wood
  • 5,648
  • 2
  • 35
  • 47
  • Related to my response below, your code seems to use `${CMAKE_CURRENT_SRC_DIR}`, which, unless you've defined this yourself, is *not* a variable populated by CMake. You may want `${CMAKE_CURRENT_SOURCE_DIR}` instead. Regarding your new issue, it is seemingly unrelated to your original problem, but you may try adding `add_custom_target` using the idiom described in [this](https://stackoverflow.com/a/26211863/3987854) post to ensure the generated source file is *only* updated when needed. – Kevin Jul 08 '20 at 22:46
  • That doesn't seem to work for me: I need to add the generated source files as sources to the executables, which makes them directly depend on them. Adding a target "in between" doesn't work therefore. For this reason I couldn't use your solution and used a different approach. I'll add that as 'answer' too. – Carlo Wood Jul 09 '20 at 02:52
  • 1
    With regards to CMAKE_CURRENT_SRC_DIR... Thank you. I did not define it myself, but both work for some reason (maybe this typo is "supported" :p). Nevertheless, I just editted the question and fixed it to what the documentation says is right. Thanks again. – Carlo Wood Jul 17 '20 at 22:46

2 Answers2

2

I ended up creating an OBJECT library of the generated source file(s) and then "link" with that:

...
#================================================================
# GENERATED SOURCE FILES
#

add_executable(table_gen table_gen.cxx)

add_custom_command(OUTPUT chattr.tab.cpp
  DEPENDS table_gen
  COMMAND ./table_gen > chattr.tab.cpp
)

add_custom_command(OUTPUT PgnGrammar.h
  DEPENDS generate_PgnGrammar.h.sh
  COMMAND ${CMAKE_CURRENT_LIST_DIR}/generate_PgnGrammar.h.sh
)

add_library(generated_ObjLib OBJECT)
target_sources(generated_ObjLib
  PRIVATE
    "chattr.tab.cpp"
    "PgnGrammar.h"
)

target_include_directories(generated_ObjLib
  PRIVATE
    "${CMAKE_CURRENT_SOURCE_DIR}" # For local header files.
)

add_library(generated::sources ALIAS generated_ObjLib)

#==================================================================
# TEST EXECUTABLES
#

add_executable(tstchessposition tstchessposition.cxx)
target_link_libraries(tstchessposition PRIVATE CWChessboard::position AICxx::cwds)

add_executable(tstbenchmark tstbenchmark.cxx)
target_link_libraries(tstbenchmark PRIVATE CWChessboard::position AICxx::cwds)

add_executable(tstpgnread tstpgnread.cxx PgnDatabase.cxx MemoryBlockList.cxx)
target_link_libraries(tstpgnread PRIVATE generated::sources CWChessboard::position AICxx::cwds)

add_executable(tsticonv tsticonv.cxx)
target_link_libraries(tsticonv PRIVATE PkgConfig::glibmm)

add_executable(tstpgn tstpgn.cxx PgnDatabase.cxx MemoryBlockList.cxx)
target_link_libraries(tstpgn PRIVATE generated::sources CWChessboard::position AICxx::cwds)

add_executable(tstspirit tstspirit.cxx PgnGrammar.h)
target_include_directories(tstspirit PUBLIC "${top_objdir}")

The trick being add_library(generated_ObjLib OBJECT) and below, and then linking with generated::sources.

Carlo Wood
  • 5,648
  • 2
  • 35
  • 47
  • Thanks for your response. Please remember to mark an answer as **accepted** upon finding a solution that works for you. Questions that have no upvoted answers nor accepted answers will remain in an *unresolved* state. – Kevin Jul 10 '20 at 13:31
  • 1
    You're right, that is not good. The reason I didn't accept mine is because it felt rude towards you. While I felt I couldn't accept yours either, because I honestly tried your solution and it just wasn't enough for my specific case in the end. The plan was to wait a while and then mark my answer as accepted when you had forgotten all about it ;). Thanks for the reminder, I had forgotten all about it. – Carlo Wood Jul 17 '20 at 22:38
1

In the same vein as the "override compile flags for single files" post, you can modify the INCLUDE_DIRECTORIES source file property for a single file:

set_source_files_properties(chattr.tab.cpp PROPERTIES 
    INCLUDE_DIRECTORIES ${CMAKE_SOURCE_DIR}/other/include/dir
)
Kevin
  • 16,549
  • 8
  • 60
  • 74
  • Thank you, this works. But there is a remaining problem. This comment is too small to add the specifics, so allow me to edit the question to add that :/. – Carlo Wood Jul 08 '20 at 21:06