Why CMake add_custom_command with DEPFILE reruns every time?

I’m trying to write my cmake script as follows:

set(OUTPUT_FILE "${CMAKE_BINARY_DIR}/static_init/generated/${target}/static_init.cpp")
set(DEP_FILE "${CMAKE_BINARY_DIR}/static_init/input/${target}.d")
write_file(${DEP_FILE} "${OUTPUT_FILE}: ")

add_custom_command(
     OUTPUT ${OUTPUT_FILE}
     COMMAND ${Python3_EXECUTABLE} myscript.py
     DEPFILE ${DEP_FILE}
     VERBATIM)

I expect, that I will populate .d file during my script first launch and later custom command will be rerun only when one of files listed after colon will change. Instead command is running during every compilation, even with empty dependencies list. Printing my own sources during cmake run also leads me to constant command rerunning. What am I doing (or understanding) wrong?

CMake
3.18.5
Ninja Clang

Due to Ninja behavior, it seems that a dep file without any dependencies (so exactly what you have in your example) imply that the command is rerun at each launch.

Now, I jus tested that, when a depfile have some dependencies, the command is run just the first time. In your case, are you sure that the depfile you generate has the correct format?

My first try was absolute source paths separated by spaces, it was the same. Maybe separator should be \n?

The format is explained here, under DEPFILE option.

Space is OK as separator. But are you sure that all files specified as dependencies exist? Moreover, the depfile is transformed by CMake before to be consumed by ninja. Can you check the effective file used by ninja? This file is under <build-dir>/CMakeFiles/d directory.

You can try Ninja to tell you why it’s rebuilding: ninja -d explain

Yes, also found that option. Problem was that DEPFILE parameter and target in dep file should be relative to build dir, not absolute.

Not at all. Absolute paths are perfectly valid and supported. See also CMP0116 which is relative to paths in depfile.

Maybe toolchain we are using isn’t the latest, but ninja -d explain messages was clear, they said, that there was absolute path where relative one was expected and when I fixed it - everything was ok.

AFAIK you need CMake 3.20 for the handling of absolute paths. @Crazy_Sage uses 3.18