Sam
Sam

Reputation: 164

Why does Visual Studio keep building files that have not changed?

I'm using Visual Studio Enterprise 2019, and I'm curious about something I've noticed for a long time but never asked because it's not breaking anything: when building a solution, the final message looks like:

========== Build: 37 succeeded, 0 failed, 168 up-to-date, 0 skipped ==========

My understanding is that VS will only build files that changed (directly or via a dependency). But that doesn't seem to be the case, here's what I get after running several builds back to back right after the first build mentioned above and without making any changes to any part of the solution:

========== Build: 15 succeeded, 0 failed, 190 up-to-date, 0 skipped ==========

========== Build: 5 succeeded, 0 failed, 200 up-to-date, 0 skipped ==========

========== Build: 16 succeeded, 0 failed, 189 up-to-date, 0 skipped ==========

========== Build: 5 succeeded, 0 failed, 200 up-to-date, 0 skipped ==========

========== Build: 22 succeeded, 0 failed, 183 up-to-date, 0 skipped ==========

....and so on.

But I don't remember ever getting:

========== Build: 0 succeeded, 0 failed, 205 up-to-date, 0 skipped ==========

Why?

Note: I have seen "0 succeeded" in smaller solutions, so it's not like it never happens

Upvotes: 3

Views: 1520

Answers (1)

Jonathan Dodds
Jonathan Dodds

Reputation: 5208

Projects are MSBuild files. Either directly or implicitly MSBuild is trying to check inputs against outputs to determine if a target should be run.

On the highest verbosity level which is 'diagnostic', MSBuild will provide information on why a project is being built.

But, in no specific order, here are some common situations that will cause a project to always build:

  1. If a file in the project has the "Copy to Output Directory" property set to "Copy Always", the project will always build to fulfill the copy.
    • Use "Copy if newer" instead of "Copy Always".
    • In MSBuild this property is the CopyToOutputDirectory attribute and the values Always and PreserveNewest are "Copy Always" and "Copy if newer", respectively.
  2. In a C# project, the pre and post build steps/events offered in the GUI project settings will cause a project to always build. Similarly in a C++ project the PreBuildEvent, PreLinkEvent, and PostBuildEvent have the same issue.
    • These items don't provide for specifying outputs and MSBuild has to always build the project because without outputs it can't determine if the step is already satisfied.
    • These items just shell-out to run shell commands and most often the shell command is a copy command. The MSBuild Copy task can replace usages like this. The Copy task has implicit inputs and outputs and runs in-process. Other commands can be run via an Exec task.
  3. In a C++ project a CustomBuildStep that doesn't specify outputs will cause a project to always build.
    • The CustomBuildStep does supports specifying outputs, but if outputs are not specified the CustomBuildStep will always run.
  4. A file that is copied or otherwise injected that is treated as an output but whose timestamp is always older than the related inputs.
    • i.e. The inputs have changed since the timestamp of the output therefore the output must be 'produced'.

Upvotes: 8

Related Questions