c++visual-studiomsbuildvisual-studio-2022incremental-build

Visual Studio C++ Influence Up-To-Date Check


I have a project that copies certain files to its output folder on build. The problem is these files can change independent of the actual project, at which point Visual Studio claims that everything is up-to-date and does not run my copy tasks.

Is there a way to tell Visual Studio to run a target/copy job if certain input files changed?

The original solution was the following (documentation):

  <Target Name="CopyDependencies" BeforeTargets="Build" 
      Inputs="AbsolutePath\To\SomeFile.txt" 
      Outputs="$(OutDir)\SomeFile.txt">
    <Copy SourceFiles="AbsolutePath\To\SomeFile.txt" DestinationFolder="$(OutDir)" />
  </Target>

but that results in

1>------ Up-To-Date check: Project: MyProject.vcxproj, Configuration: Debug Win32 ------
1>All outputs are up-to-date.

even if I write to SomeFile.txt after the last build.

I also tried to manually create a CC.write.1.tlog file (before spending the time writing the code to generate it automatically) with:

^ABSOLUTE\PATH\TO\SOMEFILE.TXT
ABSOLUTE\PATH\TO\OUTDIR\SOMEFILE.TXT

to see if that would make VS consider the file as input in its up-to-date algorithm, but that also fails.


Solution

  • I copied your target into my .vcxproj file and can reproduce the same issue at my side. I found a workaround to avoid skipping target "CopyDependencies" because all output files are up-to-date with respect to the input file even if you write to SomeFile.txt after the last build.

    Please set the property DisableFastUpToDateCheck as true in the Globals property group of your project file to override the visual studio behavior.

    <PropertyGroup Label="Globals">
        <DisableFastUpToDateCheck>true</DisableFastUpToDateCheck>
    </PropertyGroup>
    

    As the doc noted,

    A boolean value that applies to Visual Studio only. The Visual Studio build manager uses a process called FastUpToDateCheck to determine whether a project must be rebuilt to be up to date. This process is faster than using MSBuild to determine this. Setting the DisableFastUpToDateCheck property to true lets you bypass the Visual Studio build manager and force it to use MSBuild to determine whether the project is up to date.

    Besides, you can run msbuild command to watch the process of build like this and see MSBuild determine whether the project is up to date.

    enter image description here enter image description here

    UPDATE

    I guess that would be a workaround, but comes with performance implications.

    Yes, disabling the VS fast up-to-date check will make your builds much slower. Instead, you can use UpToDateCheckInput and UpToDateCheckOutput to describe an input/output file that MSBuild would not otherwise know about.

    <ItemGroup>
      <UpToDateCheckInput Include="bsolutePath\To\SomeFile.txt"" />
      <UpToDateCheckOutput Include="$(OutDir)\SomeFile.txt"" />
    </ItemGroup>
    

    In your case you can also use UpToDateCheckBuilt as there is both an input and an output. If certain input files changed, it is rebuilt.

    <ItemGroup>
        <UpToDateCheckBuilt Include="$(OutDir)\SomeFile.txt"" Original="AbsolutePath\To\SomeFile.txt" />
    </ItemGroup>
    

    Docs referred:

    up-to-date-check