We have a code generator that generates communication protocol definitions into several C ++ files and wants to switch our build system to using cmake. I made a sample project to demonstrate the problem we are facing.
The code generator accepts an input file and can generate hundreds of output files, so listing them in CMakeLists.txt not an option, especially because the protocol changes during development. We do not want to use wildcards for this.
We did not find a way to make cmake regenerate makefiles, if one of them makes changes to the file, according to the documentation, we believe configure_file should do this, but apparently it does not work on this task.
We want the make file for the main project (in the main folder in the example) to be regenerated by cmake whenever the generator code (in the gen in the example) or the protocol definition file (in our example, in.txt ) in.txt .
I have the following file structure:
src ├── CMakeLists.txt ├── gen │ ├── CMakeLists.txt │ └── gen.cpp ├── in.txt └── main ├── CMakeLists.txt └── main.cpp
with the following contents: SRC / CMakeLists.txt:
cmake_minimum_required(VERSION 3.5.1) project(cmake-config) add_subdirectory(main) add_subdirectory(gen) add_dependencies(main gen run_gen)
GEN / CMakeLists.txt:
cmake_minimum_required(VERSION 3.5.1) project(gen) add_executable(gen gen.cpp) add_custom_target( run_gen COMMAND ./gen ${CMAKE_SOURCE_DIR}/in.txt COMMENT running gen ) add_dependencies(run_gen gen)
GEN / gen.cpp:
#include <fstream> #include <string> using namespace std; int main(int argc, char *argv[]){ ifstream inf(argv[1]); ofstream outf("input.txt"); string word; while(inf >> word) outf << "set(SOURCES ${SOURCES} " << word << ")\n"; }
Main / CMakeLists.txt:
cmake_minimum_required(VERSION 3.5.1) project(main) if(NOT EXISTS ${CMAKE_CURRENT_BINARY_DIR}/../gen/input.txt) file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/../gen/input.txt "") endif() configure_file(${CMAKE_CURRENT_BINARY_DIR}/../gen/input.txt ${CMAKE_CURRENT_BINARY_DIR}/input.txt COPYONLY) set(SOURCES main.cpp) include(${CMAKE_CURRENT_BINARY_DIR}/input.txt) message(${SOURCES}) add_executable(main ${SOURCES})
Main / main.cpp:
int main(){}
gen generates input.txt with src/in.txt . input.txt contains a list of source files that I want to use to build main :
set(SOURCES ${SOURCES} a.cpp) set(SOURCES ${SOURCES} b.cpp) set(SOURCES ${SOURCES} c.cpp)
We are looking for a solution that does not require a reboot of cmake or requires a restart at each protocol change during development. This is easily achievable, but undesirable, as it leads to problematic code that ultimately uses older protocol definitions if one of the team does not understand that the protocol file (or generator) has been modified.