'Cmake executable with auto-generated sources

I want to make an executable from, for example, test_runner.cpp:

add_executable(myexe ${CMAKE_CURRENT_BINARY_DIR}/test_runner.cpp)

But this particular cpp file is itself auto-generated in a pre-build command:

add_custom_command(
    TARGET myexe PRE_BUILD
    COMMAND deps/cxxtest-4.4/bin/cxxtestgen --error-printer -o "${CMAKE_CURRENT_BINARY_DIR}/test_runner.cpp" src/My_test_suite.h
    WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
)

But now I can't generate new cmake build files because it complains about the missing source, which is indeed missing until pre-build.



Solution 1:[1]

The crux of the issue is to apply the GENERATED property to "test_runner.cpp". This tells CMake not to check for its existence at configure time, since it gets created as part of the build process.

You can apply this property manually (e.g. using set_source_files_properties). However, the proper way to handle this is to use the other form of add_custom_command, i.e. add_custom_command(OUTPUT ...) rather than add_custom_command(TARGET ...).

If you specify "test_runner.cpp" as the output of the add_custom_command(OUTPUT ...) call, then any target consuming it (in this case "myexe") will cause the custom command to be invoked before that target is built.

So you really only need to change your code to something like:

set(TestRunner "${CMAKE_CURRENT_BINARY_DIR}/test_runner.cpp")
add_executable(myexe ${TestRunner})
add_custom_command(
    OUTPUT ${TestRunner}
    COMMAND deps/cxxtest-4.4/bin/cxxtestgen --error-printer -o "${TestRunner}" src/My_test_suite.h
    WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
)

Solution 2:[2]

In my case the generated file might be re-generated on each build (it captures the current state of the git repo and embeds it into the resulting binaries). Hence the accepted approach does not work. I was able to achieve the necessary behavior with the BYPRODUCTS option of the add_custom_target command:

add_custom_target(gen_revision_info ALL 
  COMMAND gen_revision_info.py --output revision_info.cpp
  BYPRODUCTS revision_info.cpp)

add_library(revision_info revision_info.cpp)

Now anyone can link with revision_info target and have the latest git info embedded in the binaries.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Fraser
Solution 2 Mikhail