Demystifying fast up-to-date check in Visual Studio C# projects
Fast up-to-date check was created in an attempt to mitigate performance issues with incremental builds in MSBUILD. Indeed if you have many projects it would take considerable amount of time to evaluate each of them and check timestamps on all input and output files. Instead Microsoft decided to implement a simplified version of these checks that would run faster without involving MSBUILD engine. As a result this "feature" only works with "native" targets and if you have any kind of customization where external inputs or outputs are used then you'll have "misfires" sometimes. Below is some information I was able to figure out that can help you mitigate those issues. It's based on my own investigation therefore it may be not accurate enough. At least this is the most complete description that you'll find on the web.
It will help you a lot in troubleshooting if you enable up-to-date check logging. Go to HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\12.0\General and create DWORD key U2DCheckVerbosity with value set to 1. As an alternative you can enable diagnostic logging in Visual Studio but that will generate a bunch of garbage that you won't need.
Fast up-to-date check is performed by devenv.exe when build action is triggered. If check succeeds then build is marked as up-to-date and build doesn't proceed. Otherwise MSBUILD build target is invoked and the following message is logged.
Project 'xxx' is not up to date. Input file 'xxx' is modified after output file ''.
In order to perform this check Visual Studio compares last modified timestamps of input project files to corresponding timestamps of output files. This is very similar to what MSBUILD does but the difference in how it chooses these files. File is treated as input only in case it is visible in GUI. If it's not visible for some reason (for instance visible property is set to false) then it will be skipped. File links work as well. All assembly references are also treated as inputs. If any of input files is newer than its output file or any output file is missing then U2DCheck fails. Inputs and Outputs:
All visible project files are treated as inputs for primary outputs including assembly, symbols, files in obj folder.
All files with "Copy to Output Directory" setting have corresponding outputs in output folder. Avoid using "Copy Always" value as it forces U2DCheck to fail permanently.
References with "Copy Local" setting also have their outputs in output folder. Pay attention that satellite assemblies are ignored.
Also up-to-date check fails if there are open unsaved files in Visual Studio.
Fast up-to-date check can be disabled by specifying DisableFastUpToDateCheck property in csproj file. Please be prepared to experience substantial performance degradation. MSBUILD will be invoked on each project build.
I'd like to emphasize two features of U2DCheck that may help you overcome its restrictions in your customized builds.
First one is file links. In case you consume some external files in your targets you can include them into project as links. This will force Visual Studio to monitor them for changes.
Second one is a bit ugly but still useful. If you generate some files during build you can create a prototype of generated artifact in your project and set "Copy to Output Directory" to "Preserve Newest". This will make Visual Studio monitor this artifact as output. In case it is removed U2DCheck will fail. That's it.
It will help you a lot in troubleshooting if you enable up-to-date check logging. Go to HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\12.0\General and create DWORD key U2DCheckVerbosity with value set to 1. As an alternative you can enable diagnostic logging in Visual Studio but that will generate a bunch of garbage that you won't need.
Fast up-to-date check is performed by devenv.exe when build action is triggered. If check succeeds then build is marked as up-to-date and build doesn't proceed. Otherwise MSBUILD build target is invoked and the following message is logged.
Project 'xxx' is not up to date. Input file 'xxx' is modified after output file ''.
In order to perform this check Visual Studio compares last modified timestamps of input project files to corresponding timestamps of output files. This is very similar to what MSBUILD does but the difference in how it chooses these files. File is treated as input only in case it is visible in GUI. If it's not visible for some reason (for instance visible property is set to false) then it will be skipped. File links work as well. All assembly references are also treated as inputs. If any of input files is newer than its output file or any output file is missing then U2DCheck fails. Inputs and Outputs:
All visible project files are treated as inputs for primary outputs including assembly, symbols, files in obj folder.
All files with "Copy to Output Directory" setting have corresponding outputs in output folder. Avoid using "Copy Always" value as it forces U2DCheck to fail permanently.
References with "Copy Local" setting also have their outputs in output folder. Pay attention that satellite assemblies are ignored.
Also up-to-date check fails if there are open unsaved files in Visual Studio.
Fast up-to-date check can be disabled by specifying DisableFastUpToDateCheck property in csproj file. Please be prepared to experience substantial performance degradation. MSBUILD will be invoked on each project build.
I'd like to emphasize two features of U2DCheck that may help you overcome its restrictions in your customized builds.
First one is file links. In case you consume some external files in your targets you can include them into project as links. This will force Visual Studio to monitor them for changes.
Second one is a bit ugly but still useful. If you generate some files during build you can create a prototype of generated artifact in your project and set "Copy to Output Directory" to "Preserve Newest". This will make Visual Studio monitor this artifact as output. In case it is removed U2DCheck will fail. That's it.
Dear Raman,
ReplyDeleteI'm struggling with U2DCheck in VS 15.7.5 - maybe you can help me?
I have two Utility-type projects with custom build targets that depend on a list of certain files. I created a custom build Target in vxcproj with appropriate Inputs & Outputs. MSBuild worked just fine, but U2DCheck was forcing VS to run MSBuild every time because of missing lastbuildstate file. Renaming custom build target and setting it as a dependency of MS-defined Build stage fixed that (AfterTargets="Build") - now standard Build target was making necessary .lastbuildstate and then triggering my build. And everything worked just fine in a full build mode or in console. MSBuild? Works. VStudio don't rebuild every time? Works. But incremental build is still a mess - U2DCheck fails to notice any changes in files that were included into the project without any apparent reason. Can you give some directions where to look or how to debug it?
It was supposed to be simple: here's a list of files included in project, here's a .lastbuildstate file. If one of the project files is older than lastbuildstate then rebuild. But it DOES NOT work this way. Any suggestions? From how things look like I'm pretty sure that U2DCheck does not build its list of input files as "everything that is included and visible in project".