add_custom_command for OUTPUT that is updated only on change

I have the following CMake custom command:

    add_custom_command (
        OUTPUT ${outCpp} ${outHpp} ${outBin}
        COMMAND ${layout-packer-app}
            -o ${outCpp}
            -O ${outHpp}
            -B ${outBin}
            ${yamlFile}
        DEPENDS ${layout-packer-dep} ${yamlFile}
        WORKING_DIRECTORY ${inYamlDir}
    )

The command runs ${layout-packer-app}, which parses ${yamlFile} and generates ${outCpp} ${outHpp} and ${outBin}

${outCpp} and ${outHpp} are C++ source files. ${outBin} is a binary, used at runtime.

There are other source files in the project, that depend on ${outCpp} and ${outHpp}

As a result, if I modify ${yamlFile} , the command runs, and then the files that depend on ${outCpp} and ${outHpp} are rebuilt. This is fine.

I made an optimization in ${layout-packer-app} , so that ${outCpp} and ${outHpp} are generated only if their contents was changed (If the file exists and it’s contents is the same as the newly generated contents, the file is not replaced). Not every change in ${yamlFile} results to a change in ${outCpp} and ${outHpp}

As a result, sources depending on ${outCpp} and ${outHpp} are rebuilt correctly. But the issue is that COMMAND ${layout-packer-app} runs on every build, after a single modification of .yaml, which did NOT led to ${outCpp} and ${outHpp} regeneration. We assume that ${layout-packer-app} is relatively expensive, because it parses .yaml files. How to make it run only on ${yamlFile} change, like before?

I tried creating a timestamp file every time, and adding a new command, so that all output files depend on the timestamp file

add_custom_command (
OUTPUT “${stampFile}”
COMMAND ${layout-packer-app}
-o ${outCpp}
-O ${outHpp}
-B ${outBin}
${yamlFile}
# This ‘touch’ ensures the stamp file is always newer than the yamlFile
COMMAND ${CMAKE_COMMAND} -E touch “${stampFile}”
DEPENDS ${layout-packer-dep} ${yamlFile}
WORKING_DIRECTORY ${inYamlDir}
COMMENT “Running layout-packer-app for ${yamlFile}”
)

add_custom_command(
OUTPUT ${outCpp} ${outHpp} ${outBin}
DEPENDS “${stampFile}”
COMMENT “Checking layout-packer outputs”
)

This solves the dependency tracking. Now on each rebuild, only the stampFile command is executed. On yaml file change, the layout-packer-app command is executed, which decides whether to update ${outCpp} and ${outHpp}

But another issue comes - if I delete ${outCpp} or ${outHpp}, CMake does not know how to recreate them, and targets, depending on them fail to build.

I tried defining the OUTPUT files as BYPRODUCTS, but then targets that depend on them are not rebuild on their (real) change.

Is there any clean CMake solution for this? It sound like a valid use case. File A is used by a custom command to generate file B, and target C depends on file B. But not every modification of A leads to change in B, so C is not required to be rebuilt in these cases.