I’m trying to use cmake for our build system. We use autocode generators to generate code from models.
These models are parsed to get dependencies between them and so, regenerate the impacted code if one of them changed. This is currently working pretty well with add_custom_commands and add_custom_targets.
There are multiple targets that generate code and can therefor change the list of files to compile. The list of file depends on the model and its generation options.
Now, I would like to collect the generated files without manually maintaining the list of them (there are a lot) and build libraries or binaries with cmake targets. I can create these targets and add dependencies to the custom targets that generate code, but I also want to update the project with the list of files.
I have used directory property CMAKE_CONFIGURE_DEPENDS for each autocode generation that causes cmake to reconfigure the project when the list of source files change.
The problem I’m facing is that the regeneration is triggered as soon as a custom target generate code, causing multiple reconfigurations and re-builds (one for each code generation).
I’m having troubles to figure out the correct design. Has someone done these kind of things?
Regards
# Note: globbing sources is considered bad practice as CMake's generators may not detect new files
# automatically. Keep that in mind when changing files, or explicitly mention them here.
file(GLOB_RECURSE headers CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/include/*.h")
file(GLOB_RECURSE sources CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/source/*.cpp")
you may also generate CMakeLists.txt for generated subdirectories to build libraries and dependencies between them, or not?
Using code generators with file globbing is a recipe for disaster. If your code generator changes the names of the files it generates, it will leave behind the old file names. The project then globs the files and gets both the old and new files and tries to build them all. If you’re lucky, you’ll get a build error. If you’re a bit less lucky, the build will succeed but the old things won’t adversely affect whatever you’re adding them to. If you’re unlucky, the build will succeed, and the old things will change the built binary in ways you may not have expected and don’t immediately notice.
Also note that file globbing would occur at configure time. If the code generator runs at build time, then you’d end up with the file globbing finding the files from the previous build.
If the code generator runs at configure time rather than build time, then have the code generator write out a file_list.cmake to the output directory. In that file, it would set a variable to the list of files it generated. In your project’s CMakeList.txt file, you would include(/path/to/output/dir/file_list.cmake) and then use that variable to add the files to the desired CMake target. I’d avoid having the code generator write out a full CMakeLists.txt file and bringing that in with add_subdirectory(). By writing just a simple file_list.cmake, the code generator can focus on its job (generating files) without having to worry about other CMake aspects like targets, header search paths, compiler definitions and options, etc.
I’ve been reading your posts and got a better place than before. Is not yet perfect but sufficient.
I have finally opted for a target dedicated to code generation after deleting folder contents, and a collection of files using GLOB CONFIGURE_DEPENDS, plus an script that will run cmake twice to be sure the job is done.
I’m now facing another problem because of submodules, but I will create another post.