Reputation: 127
I've been caught out by an add_custom_command w/target declaration problem and present it here. Below are two CMake source trees, the first one runs the custom command while the second version does not.
QQ. I expected the two trees to be (roughly equivalent) - why would the latter skip running the custom command?
V1: Building generates myFile.txt
# ~/CMakeLists.txt
project(myProj)
cmake_minimum_required(VERSION 3.16)
add_subdirectory(myDir)
# ~/myDir/CMakeLists.txt
add_executable(myExe) # ***Declare target here***
add_custom_command(
OUTPUT myFile.txt
COMMAND touch myFile.txt
DEPENDS myFile.txt
)
target_sources(myExe PRIVATE myFile.txt)
V2: Building doesn't generate a myFile.txt
# ~/myDir/CMakeLists.txt
project(myProj)
cmake_minimum_required(VERSION 3.16)
add_executable(myExe) # ***Declare target here***
add_subdirectory(myDir)
# ~/myDir/CMakeLists.txt
add_custom_command(
OUTPUT myFile.txt
COMMAND touch myFile.txt
DEPENDS myFile.txt
)
target_sources(myExe PRIVATE myFile.txt)
I've been tearing my hair out and didn't turn up much after skimming the reference. Cheers
Upvotes: 1
Views: 612
Reputation: 19946
This is an unfortunate limitation of CMake, but it is documented. You can only attach generated source files to targets created in the same directory:
This defines a command to generate specified
OUTPUT
file(s). A target created in the same directory (CMakeLists.txt
file) that specifies any output of the custom command as a source file is given a rule to generate the file using the command at build time.
Emphasis mine. See the original documentation here: https://cmake.org/cmake/help/latest/command/add_custom_command.html
You can work around this by using OBJECT libraries, like so:
# ./myDir/CMakeLists.txt
add_custom_command(
OUTPUT myFile.cpp
COMMAND touch myFile.cpp
# The command doesn't depend on itself.
)
add_library(myExeObj OBJECT myFile.cpp)
target_link_libraries(myExe PRIVATE myExeObj)
Upvotes: 1