Project-system: Up-To-Date checks can improperly consider certain projects with runtime output as out-of-date due to binding redirects.

Created on 3 Apr 2019  路  14Comments  路  Source: dotnet/project-system

Visual Studio Version:
VS 2019 GA
Summary:
When using a project with the following constraints:

  • Common Project System
  • Library project (NUnit, unit tests)
  • Targeting net462 (probably any framework)
  • Auto-generating binding redirects
  • HasRuntimeOutput = true

The Up-To-Date checks seem to be checking the wrong input generated .dll.config file against the output file. This can eventually cause the project to be considered out-of-date in perpetuity.

Steps to Reproduce:

  1. Clone my repro solution at https://github.com/dammejed/ReproOutOfDateProjects/

  2. Build the solution a few times (F6) without changing anything.

  3. Wait for several seconds.

  4. Modify the Tests class in some meaningless way (even whitespace).

  5. Build again.

  6. Any further builds now seem to consider the project out of date.

Expected Behavior:

When building a project after no changes, the project should be considered up-to-date.

Actual Behavior:

Through some strange confluence of the above factors, the FastUpToDate check seems to be checking the wrong input file against the generated .dll.config output file. I captured the log output after enabling the Verbose FastUpToDate checks. Here's a snip below:

-- snip --
1>FastUpToDate: Checking copied output (UpToDateCheckBuilt with Original property) file 'C:\Users\Jeff\source\repos\ReproOutOfDateProjects\ReproOutOfDateProjects\obj\Debug\ReproOutOfDateProjects.dll.withSupportedRuntime.config': (ReproOutOfDateProjects)
1>FastUpToDate:     Source 4/2/2019 9:03:54 PM: 'C:\Users\Jeff\source\repos\ReproOutOfDateProjects\ReproOutOfDateProjects\obj\Debug\ReproOutOfDateProjects.dll.withSupportedRuntime.config'. (ReproOutOfDateProjects)
1>FastUpToDate:     Destination 4/2/2019 8:56:25 PM: 'C:\Users\Jeff\source\repos\ReproOutOfDateProjects\ReproOutOfDateProjects\bin\Debug\ReproOutOfDateProjects.dll.config'. (ReproOutOfDateProjects)
1>FastUpToDate: Source is newer than build output destination, not up to date. (ReproOutOfDateProjects)
1>FastUpToDate: Up to date check completed in 4.8 ms (ReproOutOfDateProjects)
1>------ Build started: Project: ReproOutOfDateProjects, Configuration: Debug Any CPU ------
-- snip --

The intermediate config file, ReproOutOfDateProjects.dll.withSupportedRuntime.config is the one being checked against the output file, ReproOutOfDateProjects.dll.config. I'd expect that, instead, the config file with the generated binding redirects, ReproOutOfDateProjects.dll.config in the obj directory is checked against the output directory.

Annoyingly, this can sometimes fix itself too if I make seemingly innocent changes to the project, such as enabling the 'show hidden files' option and build again. I suppose this is because the .user file for the project gets modified which changes the calculation.

If you have trouble reproducing, try closing the solution, deleting the obj and bin directories, and then opening and building again. That seemed to be a semi consistent way to reproduce the problem for me.

User Impact:

Because the project eventually gets considered out-of-date perpetually, incremental builds stop working for these types of projects. If this happens in a large solution with many large projects, this can drastically increase the build time and reduce developer productivity.

Please let me know if I can provide any more information.

Bug Feature-Up-to-date Triage-Approved

Most helpful comment

By the way, we tested in 16.4.3.

Let us know if you still see the issue and we can re-open this. Thanks.

All 14 comments

Of note: I didn't experience this issue in a larger solution in any of the RCs, nor do I experience this in VS2017.

@drewnoakes Can you take a look?

FYI, my workaround for this behavior was to skip the generation of this intermediate file by adding
<GenerateSupportedRuntime>false</GenerateSupportedRuntime>
to my project. In my usecase, either:

  1. I've already specified the <supportedRuntime> element, so I don't need the auto-generated one, or
  2. I don't require the <supportedRuntime> element in the generated app.config. (e.g., for the test projects in my particular usecase)

I am experiencing same (similar at least) issue VS2019 16.1.5, in my case I also have auto generated binding redirects:

13>FastUpToDate: Checking copied output (UpToDateCheckBuilt with Original property) file 'C:\projects\project\Source\Project.Name\obj\Debug\Project.Name.exe.config': (Project.Name)
13>FastUpToDate:     Source 2019-07-09 10:34:26: 'C:\projects\project\Source\Project.Name\obj\Debug\Project.Name.exe.config'. (Project.Name)
13>FastUpToDate:     Destination 2019-07-09 10:34:26: 'C:\projects\project\Source\Project.Name\bin\Debug\Project.Name.exe.config'. (Project.Name)

I have to disable both, to force FastUpToDate checker to use App.config instead of obj\...\Project.exe.config

    <GenerateSupportedRuntime>false</GenerateSupportedRuntime>
    <AutoGenerateBindingRedirects>false</AutoGenerateBindingRedirects>

It looks as if either generate supported runtime or auto generate binding redirects overwrites Original property of Copied output items.

In my case I will have to disable FastUpToDate by adding <DisableFastUpToDateCheck>true</DisableFastUpToDateCheck> as I need auto generated binding redirects.

Of note: I didn't experience this issue in a larger solution in any of the RCs, nor do I experience this in VS2017.

This is my experience as well. Loading up the same .sln in VS 2017 works perfectly fine, but we get the unnecessary rebuilds in VS 2019.

For me <DisableFastUpToDateCheck>true</DisableFastUpToDateCheck> makes everything worse because even projects flagged as up-to-date will trigger msbuild. I'm trying out leaving <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects> with <GenerateSupportedRuntime>false</GenerateSupportedRuntime>. It seems to be working better than nothing. If not, the only other option is going back to VS 2017 for my solution unfortunately :(

When fixing this bug, can you also add ability to exclude arbitrary files from FastUpToDate check? It would help unblock users if we have a similar bug in the future.

Thanks all for the detail on this issue. You shouldn't have to be disabling the up to date check as a workaround.

@dammejed I can reproduce the issue locally with the steps you provided.

@majastrz I filed #5073 to track your suggestion of excluding arbitrary files.

@drewnoakes and I tried testing this using the repo solution @dammejed provided, and we couldn't reproduce it (also tried it with different SDK versions and targets).

We are not sure what changed from our side (or other teams'), but do let us know if you see it again.
@dammejed @marius-klimantavicius @majastrz

By the way, we tested in 16.4.3.

Let us know if you still see the issue and we can re-open this. Thanks.

@drewnoakes I will undo our workaround once I get 16.4.3 installed on my box and try it out.

I confirm, I no longer require the workaround I mentioned in a larger solution on 16.4.4. Thanks for looking into this!

Awesome, thanks for following up!

Confirmed as well on 16.4.4. I can no longer reproduce the issue with the workaround removed in two repos. Awesome!

Was this page helpful?
0 / 5 - 0 ratings