Today, I feature to you a short tutorial about CMake. How to generate source files during a build! During this post, we will create a binary with CMake and generated files. Don’t hesitate to review my short tutorial about CMake basis here.
The issue - CMAKE returns an error on the generated source file
Sometimes, you could build an application with a generated files. Unfortunately, those files could be sources.
If those files don't exist during the CMake configuration, then it results in an error “No rule to make target 'GeneratedFile.cpp'”.
The Solution - Define a custom command, and change the file property
The solution is done in three steps:
- Create a custom command with the instruction “add_custom_command”. You will launch your file generator here.
- "Make depends" on this new custom target . CMake will be able to launch this target ONLY if those source files are not present.
- In your target, change the file property to “GENERATED”.
- EXTRA: In your custom command, you can also add a “DEPENDS” instruction. This command helps CMake to control your custom target and then apply launching rules when dependencies change.
If you apply it, your CMake can control perfectly your file generator!
The Example - A simple C++ file
CMAKE - Generate source file with custom target
cmake_minimum_required(VERSION 3.8) project(GeneratedFileProject) # Set generated file set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/GeneratedFile.cpp PROPERTIES GENERATED 1) add_executable(GeneratedExecutable GeneratedFile.cpp) #Generator definition - Custom Target add_custom_command(COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/fileGenerator.sh OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/GeneratedFile.cpp DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/fileGenerator.sh COMMENT "Generating GeneratedFile.cpp" ) add_custom_target(gen_bar DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/bar.cpp)
As you see here, I applied the instructions:
- I create a custom target to launch my fileGenerator.sh
- I make depends on this custom target to the generated file.
- I set this file as “GENERATED” in my new target.
- I make DEPENDS it directly on my file generator script to relaunch it in case of modification.
Now, I can launch my CMake configuration and build the program!
As you see, the configuration is pretty simple!