2

Imagine a code generator which reads an input file (say a UML class diagram) and produces an arbitrary number of source files which I want to be handled in my project. (to draw a simple picture let's assume the code generator just produces .cpp files).

The problem is now the number of files generated depends on the input file and thus is not known when writing the CMakeLists.txt file or even in CMakes configure step. E.g.:

>>> code-gen uml.xml
generate class1.cpp..
generate class2.cpp..
generate class3.cpp..

What's the recommended way to handle generated files in such a case? You could use FILE(GLOB.. ) to collect the file names after running code-gen the first time but this is discouraged because CMake would not know any files on the first run and later it would not recognize when the number of files changes.

I could think of some approaches but I don't know if CMake covers them, e.g.:

  • (somehow) define a dependency from an input file (uml.xml in my example) to a variable (list with generated file names)

  • in case the code generator can be convinced to tell which files it generates the output of code-gen could be used to create a list of input file names. (would lead to similar problems but at least I would not have to use GLOB which might collect old files)

  • just define a custom target which runs the code generator and handles the output files without CMake (don't like this option)

Update: This question targets a similar problem but just asks how to glob generated files which does not address how to re-configure when the input file changes.

frans
  • 8,868
  • 11
  • 58
  • 132
  • Have you checked this question: https://stackoverflow.com/questions/44076307/cmake-globbing-generated-files? It describes the situation similar to yours one. – Tsyvarev Jun 07 '17 at 08:19
  • I normally re-implement the naming logic of the generator in my CMake script (reading the input file and parsing it to get the information). Can you please give an example of the `uml.xml` content? Which UML tool are you using? – Florian Jun 07 '17 at 08:22
  • This tool is just fictitious - I'm interested in the general approach. The problem is that the content of such a file might change so CMake would have to re-configure in such a case. – frans Jun 07 '17 at 08:27
  • `... which does not address how to re-configure when the input file changes.` - Reconfiguration on file change is asked here: https://stackoverflow.com/questions/24246037/how-to-make-cmake-reconfiguration-depend-on-custom-file. This aspect is also noted in [my answer](https://stackoverflow.com/a/44078192/3440745). – Tsyvarev Jun 07 '17 at 09:31
  • Possible duplicate of https://stackoverflow.com/questions/4222326/cmake-compiling-generated-files/39258996#39258996. – Florian Jun 07 '17 at 10:00

1 Answers1

2

Together with Tsyvarev's answer and some more googling I came up with the following CMakeList.txt which does what I want:

project(generated)
cmake_minimum_required(VERSION 3.6)
set(IN_FILE "${CMAKE_SOURCE_DIR}/input.txt")
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${IN_FILE}")
execute_process(
    COMMAND python3 "${CMAKE_SOURCE_DIR}/code-gen" "${IN_FILE}"
    WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
    INPUT_FILE "${IN_FILE}"
    OUTPUT_VARIABLE GENERATED_FILES
    OUTPUT_STRIP_TRAILING_WHITESPACE
)
add_executable(generated main.cpp ${GENERATED_FILES})

It turns an input file (input.txt) into output files using code-gen and compiles them.

execute_process is being executed in the configure step and the set_property() command makes sure CMake is being re-run when the input file changes.

Note: in this example the code-generator must print a CMake-friendly list on stdout which is nice if you can modify the code generator. FILE(GLOB..) would do the trick too but this would for sure lead to problems (e.g. old generated files being compiled, too, colleagues complaining about your code etc.)

PS: I don't like to answer my own questions - If you come up with a nicer or cleaner solution in the next couple of days I'll take yours!

frans
  • 8,868
  • 11
  • 58
  • 132