I'm in the process of generating an api using flatbuffers within cmake. Now when on top level of the cmake directory tree the api is generated, the include files that should be generated are not found when they are needed in the branches.
./CMakeLists.txt
set(INTERFACE_FBS ${CMAKE_CURRENT_SOURCE_DIR}/fbs/testapi.fbs)
flatbuffers_generate_headers(TARGET incl
SCHEMAS ${INTERFACE_FBS}
FLAGS --scoped-enums --cpp-std c++17)
target_link_libraries(incl INTERFACE flatbuffers::flatbuffers)
set_directory_properties(PROPERTIES ADDITIONAL_CLEAN_FILES incl)
#add_executable(testapp app/src/test.cpp)
#target_link_libraries(testapp incl)
add_subdirectory(app)
./app/CMakeLists.txt
add_executable(app src/test.cpp)
target_link_libraries(app incl)
Running the system like this results in the following error:
CMake Error at app/CMakeLists.txt:2 (add_executable):
Cannot find source file:
/home/xxx/build.test/incl/testapi_generated.h
Tried extensions .c .C .c++ .cc .cpp .cxx .cu .m .M .mm .h .hh .h++ .hm
.hpp .hxx .in .txx
The testapi_generated.h
can't be found as it's not generated. But it should be generated as the function flatbuffers_generate_headers
sets an add_custom_command
for the wanted .h
file.
When I move the building of the executable to the main cmake file, so replacing the bottom of: ./CMakeLists.txt
add_executable(testapp app/src/test.cpp)
target_link_libraries(testapp incl)
#add_subdirectory(app)
the '.h' file is generated and the simple application builds without problems. Also enabling the subdirectory at that point will result in a working executable. Performing a make clean
and the building will fail again.
What am I doing wrong? Is it not possible to first use files created by an add_custom_command
in a subdirectory?
I've put the whole project into a repository: https://github.com/CedricSchmeits/file-generation-issue
As Milan Š. already stated the problem is caused by scoping. Within flatbuffers_generate_headers
the files are generated by add_custom_command
which is the correct way of generating files. Within the desciption of add_custom_command
this is already addressed with: same directory (CMakeLists.txt file)
This defines a command to generate specified OUTPUT file(s). A target created in the same directory (CMakeLists.txt file) that specifies any output of the custom command as a source file is given a rule to generate the file using the command at build time.
Further on the solution is stated:
Instead, use the add_custom_target() command to drive the command and make the other targets depend on that one.
This means that implementing another target which is depended on all the custom commands created by flatbuffers_generate_headers
would solve the problem. Then within another directory the target there should also be made depended not only of the interface library but also of the additional target. using add_dependencies
This is solved in the pull request for flatbuffers: Added GENERATE_ to flatbuffers_generate_headers which is added to release v23.3.3.
The flatbuffers_generate_headers
now not only generates the INTERFACE library ${TARGET}
but also a new target named: GENERATE_${TARGET}
. Which results that only within the sub directory a change needs to be done.
./app/CMakeLists.txt
add_executable(app src/test.cpp)
target_link_libraries(app incl)
add_dependencies(app GENERATE_incl)
Also make sure that you are using at least version 3.20 from cmake as within that version some issues with GENERATE files flags are solved.
./CMakeLists.txt
cmake_minimum_required(VERSION 3.20)