cmake: read and compile dynamically-generated list of cpp files - c++

I have a custom tool that processes a given list of IDL files and produces a number of .cpp and .h files as output. I want to add those files to the list of things to compile in my CMakeLists, and also model the dependencies those files have on the IDL.
To keep things simple, I will state that any change to any of the IDL files should trigger a regeneration of all cpp/h.
I have a custom command that takes care of running the generator tool and listing all the IDL files as dependencies.
My issue is getting the subsequent list of cpp/h files into cmake at build-time. It is not possible to infer from the name of the IDL files what cpp files will be generated. My generator tool will, however, output the list of generated files to a text file.
So my question is: how do I instruct cmake to "read from this text file and add the contents as extra source and header files to be compiled", also bearing in mind that the said text file only exists during a certain point of the build?

CMake needs to be able to infer the names of all .cpp files participating in the build at configure time. It is not possible to add files afterwards without re-running CMake.
One possible approach would be to use a two-phase CMake build: Instead of building the generated source files directly from your main project, you create a separate CMake project for building just the generated sources.
Then in your main CMake project you add a custom target that runs after the code generation and invokes CMake to both configure and build the generated files project.
The disadvantage here is that the generated files no longer appear as part of the main project. Also some trickery is required if you don't want to rebuild the generated sources every time - custom targets are always considered out-of-date, so you might want to use a script here that only runs CMake on the subproject if the generated files changed.

This is a few years late but this works just fine:
#run whatever tool that generates the cpp files
execute_process(COMMAND "./your_tool.sh")
#read files from files.txt and make a cmake 'list' out of them
file(READ "files.txt" SOURCES)
#found this technique to build the cmake list here:
#http://public.kitware.com/pipermail/cmake/2007-May/014236.html
#maybe there is a better way...
STRING(REGEX REPLACE ";" "\\\\;" SOURCES "${SOURCES}")
STRING(REGEX REPLACE "\n" ";" SOURCES "${SOURCES}")
#at this point you have your source files inside ${SOURCES}
#build a static library...?
add_library(mylib STATIC ${SOURCES})

There is a function that build the list directly from file:
file(STRINGS <filename> <variable> [<options>...])
source: https://cmake.org/cmake/help/v3.11/command/file.html

Related

how to use pb.cc to make libraries in subdirectories, i got "Cannot find source file"

I tries to use FOREACH to generated several pb files. And make two list names PROTO_SRCS & PROTO_HDRS like below.
I can use it in the main CMakeLists. Like add_executable(a SHARED ${PROTO_SRCS} main.cpp).
But I can not use this param in subdirectories to make a library. when I type "cmake .." in main CMakelists build dir. It shown that "Cannot find source file: a.pb.cc".
main CMakeLists.txt
add_library(xxx SHARED ${PROTO_SRCS})
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/src/back back)
in src/back CMakeLists.txt
add_executable(yyy ${PROTO_SRCS})
and I can use message to show ${PROTO_SRCS} in subdir so it pass into successfully.
Please help me to point out the problem. Thx a lot
The issue is that in CMake versions older than 3.20 the GENERATED property of source files is only visible in the directory where it is set. Thus, when you add the protobuf-generated source files to a target defined in a different directory, CMake will no longer know that these are files generated during the build. Consequently, CMake will try to locate these files at configuration time, when they obviously do not exist yet.
Unfortunately, at the time of writing there is only a release candidate for CMake 3.20 and no official release yet. So depending on whether you need to coordinate with other coworkers or whether you're working on this project on your own it might not be feasible to use the release candidate.
If you can't use it, the alternative is to create an object library via add_library(protobuf_objs OBJECT ${PROTO_SRCS}) in the directory where you generate the files and to use target_sources(xxx PRIVATE $<TARGET_OBJECTS:protobuf_objs>) and target_sources(yyy PRIVATE $<TARGET_OBJECTS:protobuf_objs>) instead of adding the ${PROTO_SRCS} as source files to these targets directly.

Custom CMake target that uses only CMake functions [duplicate]

I have a project under CMake with some files generated with python generator from XML files. I cannot specify all files generated by this generator in CMakeLists.txt so I use file globbing for this.
The problem is that when I update my XML files or generator sources (which are in the same repository) I would like to have my build system reconfigured so changed files are taken into account when rebuilding the code (via make for example).
Is it possible to make CMake treat some files like it treats CMakeLists.txt files and to make it regenerate build system when those file are changed?
It doesn't require any kind of workarounds. The standard way is to use CMAKE_CONFIGURE_DEPENDS property:
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS <filename>)
Yes, you should be able to do that by (ab)using configure_file(). Configuring a file makes the source a dependency of the CMake run, so that any changes in it cause a reconfiguration. Simply like this:
configure_file(MyInputFile.xml DummyOutput.xml)
Since it has been a while I will add to #roolebo's answer.
There's actually a better command to add a dependency on a file:
set_directory_properties(PROPERTIES CMAKE_CONFIGURE_DEPENDS <relative_or_full_path_to_file>)
What might be confusing is that this command adds a property to the current directory. Well, it does not matter since you can set a full path to a file that resides outside of the current directory's scope, for instance: ../../config.json

cmake: build depends on none-source files. Qt help generation

I'm trying to generate Qt help files during build.
.qhp (Qt help project), contains list of HTML files located in /html folder adjacent to .qhp file.
It works fine, if I change .qhp file. But if I change only HTML files the build is not started.
This is part of my CMakeLists.txt:
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/help.qch
COMMAND qhelpgenerator ${CMAKE_CURRENT_SOURCE_DIR}/help.qhp -o ${CMAKE_CURRENT_BINARY_DIR}/help.qch
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/help.qhp
)
ADD_CUSTOM_TARGET(${TARGET_NAME}
ALL DEPENDS
${CMAKE_CURRENT_BINARY_DIR}/help.qch
SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/uav_help.qhp
)
Q: How can I add dependencies to HTML files (w/o creating list of them in CMakeLists.txt), if I don't want to add them to the project?
Q2: Are there other ways to organize automatic .qch generation during build?
List these HTML's in DEPENDS of add_custom_command() call too, obviously.
You can also look at KDE's Extra CMake Modules project, which contains ECMAddQch macro.

How to pick source from build dir if available otherwise use source dir?

is there a way to force CMAKE pick sources form current build folder if file(s) is available otherwise take it from the source directory?
My project has following structure:
ROOT/lib/a.cpp
/BUILD
the BUILD folder is where I run cmake ... I've got an optional custom target which generates a source BUILD/lib/a.cpp file: cmake generate.
I'd like to build a library in ROOT/lib that automatically picks up the generated source file BUILD/lib/a.cpp in case it exists otherwise use ROOT/lib/a.cpp.
The library is generated with ROOT/lib/CMakeLists.txt in the following way:
add_library(test a.cpp)
(the custom rule is omitted).
you can just use the full path to generated file:
add_library(test ${CMAKE_CURRENT_BINARY_DIR}/a.cpp)
and if file doesn't exists, your custom command will be executed to generate it.
make sure that generated file produced by add_custom_command() and not by add_custom_target().

How to remove tokens from a list in cmake?

I want to exclude some source files from building when not in Windows.
What is wrong in the following CMakeLists.txt cmake file?
aux_source_directory(. SRC_LIST)
# Remove Microsoft specific files
message(${SRC_LIST})
list(REMOVE_ITEM SRC_LIST stdafx.h stdafx.cpp)
message("------------------")
message(${SRC_LIST})
The contents of the messages before and after trying to remove the two files are exactly the same.
What is wrong?
You have to specify the exact name of the element you want to remove.
In your case, aux_source_directory prepends each entry with a ./, so the correct command has to be
list(REMOVE_ITEM SRC_LIST ./stdafx.h ./stdafx.cpp)
Also, please make sure you understand the implications of using manual calls to aux_source_directory for maintaining lists of source files:
It is tempting to use this command to avoid writing the list of source
files for a library or executable target. While this seems to work,
there is no way for CMake to generate a build system that knows when a
new source file has been added. Normally the generated build system
knows when it needs to rerun CMake because the CMakeLists.txt file is
modified to add a new source. When the source is just added to the
directory without modifying this file, one would have to manually
rerun CMake to generate a build system incorporating the new file.
Quoting the documentation for aux_source_directory.