I have a custom target which produces an end result using a two-step process similar to compilation & linking. My problem is that as soon as more than one source file is involved, updates do not cascade correctly in one build.
Here’s a minimal CMakeList to reproduce the issue:
cmake_minimum_required(VERSION 3.14)
project(WhyTwoStep)
set(ins "")
set(outs "")
foreach(source IN ITEMS a.in b.in)
set(from ${CMAKE_CURRENT_SOURCE_DIR}/${source})
list(APPEND ins ${from})
set(to ${CMAKE_CURRENT_BINARY_DIR}/${source}.out)
list(APPEND outs ${to})
add_custom_command(
OUTPUT ${to}
COMMAND ${CMAKE_COMMAND} -E copy ${from} ${to}
DEPENDS ${from}
COMMENT "Pseudo-compilation of ${source}"
VERBATIM
)
endforeach()
set(final ${CMAKE_CURRENT_BINARY_DIR}/final.txt)
add_custom_command(
OUTPUT ${final}
COMMAND ${CMAKE_COMMAND} -E touch ${final}
DEPENDS ${outs}
COMMENT "Pseudo-linking"
VERBATIM
)
add_custom_target(
Finalise ALL
DEPENDS ${final}
SOURCES ${ins}
COMMENT "Checking..."
)
Generate for VS 2017. Build Solution, everything runs fine; the output I get is as expected:
2>------ Build started: Project: Finalise, Configuration: Debug Win32 ------
2>Pseudo-compilation of a.in
2>Pseudo-compilation of b.in
2>Building Custom Rule H:/REDACTED/src/CMakeLists.txt
2>Pseudo-linking
2>Checking...
Then, Build solution again, nothing happens (only get the expected Checking...
output).
Then, modify a.in
. Build solution. The output I get is:
1>------ Build started: Project: Finalise, Configuration: Debug Win32 ------
1>Pseudo-compilation of a.in
1>Checking...
I would expect Pseudo-linking to happen too, but it doesn’t. Only if I Build solution again do I get this:
1>------ Build started: Project: Finalise, Configuration: Debug Win32 ------
1>Pseudo-linking
1>Checking...
So it takes two builds of the solution to get the final file correctly up to date. Is this expected, am I doing something wrong, or should I file a bug report?
Also note that curiously, if b.in
is taken out of the equation and thus final.txt
only depends on a.in.out
, both Pseudo-compilation and Pseudo-linking happen during the first Build after modification (as I would expect to be the correct case).
(I’ve tested this with CMake 3.14.4 as well as 3.18.3, the behaviour is identical in both).