[BUG] CMake internally specified custom target output for MSBuild is never generated and causes target to always be out-of-date

Hi guys

I think there is a bug with custom targets and the Visual Studio Generator. The .vcxproj file for the custom target contains a line that specifies the MyTarget file as output of the custom target.

<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">C:\development\CustomTargetsOutOfDateReproducer\build\CMakeFiles\MyTarget</Outputs>

This output is not specified by the projects CMake code but is set by CMake internally. The problem is that the file is never generated when building the custom target which causes MSBuild to always run some extra stuff. When changing the MSBuild output to Detailed it contains a line like this:

10:35:41:442	2>    C:\development\CustomTargetsOutOfDateReproducer\build\CMakeFiles\89d5714c4b5b81289a65e2af1894767f\MyTarget.rule will be compiled because output C:\DEVELOPMENT\CUSTOMTARGETSOUTOFDATEREPRODUCER\BUILD\CMAKEFILES\MYTARGET does not exist.

which indicates that it does some extra work and the targets definately take longer to build then normal up-to-date C++ targets.

Reproducer

Generate a Visual Studio solution with the following files:

# CMakeLists.txt

cmake_minimum_required(VERSION 4.3)

project(Reproducer)

set(generatedFile ${CMAKE_CURRENT_BINARY_DIR}/MyTarget.stamp)


add_custom_command(
	COMMAND cmake -E touch ${generatedFile}
	OUTPUT ${generatedFile}
	COMMENT "Generate ${generatedFile}"
)


add_custom_target(
	MyTarget
	DEPENDS ${generatedFile}
)

CMakePresets.json

{
  "version": 10,
  "cmakeMinimumRequired": {
    "major": 4,
    "minor": 3,
    "patch": 0
  },
  "configurePresets": [
    {
      "name": "dev",
      "generator": "Visual Studio 17 2022",
      "binaryDir": "${sourceDir}/build"
    }
  ]
}

Open the generated solution and set the “MSBuild project build output verbosity” to “Detailed”
Build MyTarget twice. The output of the second build contains the log line mentioned in the introduction.

The documentation explicitly states for add_custom_target: “The target has no output file and is always considered out of date”

So is this something that is required to map custom targets to Visual Studio project files?

Because if I delete the hole block

<CustomBuild Include="C:\development\CustomTargetsOutOfDateReproducer\build\CMakeFiles\89d5714c4b5b81289a65e2af1894767f\MyTarget.rule">

and only leave the <CustomBuild block that is added to generate the stamp file it seems to behave as expected. → Nothing is done when the stamp file is up-to-date.