Visual Studio Rebuilds unmodified projects
Asked Answered
L

18

88

So, as the title reads, I have a VS2010 solution with ~50 projects in it right now. If I make a change to a "top level" project that nothing references then VS still rebuilds all 50 projects. I'm running Visual Studio 2010 Ultimate without any add-ons. I am using ILMerge to consolidate all of the projects into a single file.

I have verified this by checking the time stamps of the lower level dlls and see that they are indeed rebuilt even though their code wasn't touched.

I've read all responses and comments for:

Visual Studio 2008 keeps rebuilding

Visual studio keeps building everything

Strange VS2010 build glitch occurs in my solution

Reasons for C# projects to rebuild in Visual Studio

But most of them just offer suggestions on unloading projects to speed up build times but nothing concrete as to a fix. I'm trying to figure out why VS thinks these dependent projects need to be rebuilt when they don't and fix it.

I've turned on 'Tools > Options > Projects and Solutions > Build and Run > Only build startup projects and dependencies on run' but with no effect.

Also, if I just rebuild a "mid-level" project that only has 8 (in)direct dependencies then it still builds all 8 projects even though ILMerge isn't invoked and none of the dependent projects have been modified.

Thank you everyone for any insight you may be able to provide.

Added

To test some of the suggestions I created a new WinForms project from scratch. I then created two new projects inside that solution. I copied all of the code and resources (not project file) from my two 'lowest level' projects into the two brand new projects (I did this by dropping the files and folders from Explorer onto the project in Visual Studio).

The lowest project, let's call it B, did not reference any other project. The next project, A, referenced B only. So once I added the required .NET and external assembly references to the projects then the solution would build.

I then had my new WinForm project reference A and did a full build. So the ref chain is:

WinForm -> A -> B

I then modified WinForm only and did a standard build (F6). As before, Visual Studio rebuilt all three projects.

After some systematic eleminiation of source files in project B I found that if I removed my Resources.Designer.cs and Resources.resx (and commented out the code that made use of the .Properties.Resources object of those resources) then a modification of WinForm would no longer rebuild the entire solution and would only rebuild WinForm.

Adding the Resources.resx and Resources.Designer.cs back to project B (but leaving the referenced code commented out so that nothing was making use of the resources) would re-introduce the full build behavior.

To see if perhaps my resource files were corrupted, I deleted them again and then created a new one (via Project Properties -> Resources) and re-added the same resource as before, which was a single Excel file. With this setup the full rebuild would still occur.

I then removed the single resource, but left the resource file in project B. Even with no resources added, but the resource file still in the project, the full (unneeded) rebuild would occur.

It appears that just having a resource file added to a (.NET 3.5) project will cause Visual Studio 2010 to always rebuild that project. Is this a bug or intended/expected behavior?

Thanks all again!

Laski answered 17/2, 2013 at 0:25 Comment(9)
can you try building it with msbuild directly and see if it still happensConde
My understanding is that VS invokes msbuild (and that a project is basically an msbuild script #1497844) so I'm not sure this would change anything. I suspect I would just end up recreating the same build script and then run that from the command line. Is there some way in which running msbuild directly would be different? Or perhaps some way to find out why msbuild thinks the projects need to be rebuilt?Laski
Are you building or rebuilding?Beautiful
Normal building (F6) and sometimes project only build (Shift-F6). Both exhibit the same behavior, although the scope of the rebuilt projects of the 'project only build' is limited to the direct and indirect dependencies of the current project.Laski
@MattKlein yes I have a feeling VS does run msbuild internally but perhaps there is something with the way it invokes it that might be different, you can msbuild you sln file from the command line by doing "msbuild mysol.sln"Conde
I've got the same issue together with the build output message: "jQuery.Validation 1.8" already installed, which seems to indicate that also NuGet is invoked on every build, even when I uncheck the restore option in the settings. The only way to disable that latter behaviour is editing the NuGet.targets file and set RestorePackages to false. And then of course reload the solution, because appearantly, this file is being cache by VS sighNoodlehead
@MattKlein if you have a simple demo project showing the problem, you should report it to Microsoft - connect.microsoft.com/VisualStudioEclectic
I had this problem in a solution that referenced several hand-built .csproj files. Each project auto-included source code with <Compile Include="***.cs" Exclude="obj***.cs" />. My dependency-checking problem went away when I removed the (unnecessary) Exclude attribute. The odd thing is I had 18 projects using this pattern, but only had to change two of them to get things working. I suspect the problem is that Visual Studio can't cope with all the possible valid MSBuild syntax.Ciri
@MattKlein did you end up finding a solution? I am having the same problem now with 50 projects all being built on every build. Is the only option to not use resx files?Lajuanalake
K
163

Open Tools - Options, select Projects and Solutions - Build and Run in tree, then set "MSBuild project build output verbosity" to Diagnostic. This will output the reason for building a project, i.e.

Project 'ReferencedProject' is not up to date. Project item 'c:\some.xml' has 'Copy to Output Directory' attribute set to 'Copy always'.

or

Project 'MyProject' is not up to date. Input file 'c:\ReferencedProject.dll' is modified after output file 'c:\MyProject.pdb'.

In this case the fix is to copy some.xml only if newer.

Pre and post build events can trigger build as well.

Kalliekallista answered 15/4, 2015 at 11:40 Comment(12)
I believe this is the best answer, as it brings you to a point of actually understanding what is causing the builds to be repeated, rather than just guessing or experimenting.Adkison
Nice to know! I was wandering why a project rebuild also rebuilds all referenced projects. The diagnostic logging explains: 'Target "CleanReferencedProjects: (TargetId:8)"' :)Cormier
Thanks, this is just what I needed. In my case it turned out that the constant building was triggered by a .ico file set to "Copy always."Encephalo
This answer is actually very helpful. +1Hyperplasia
More detailed article oz-code.com/blog/…Ultra
I have this same issue, however I set my logging to verbose and it still doesn't output a single line telling me why it thinks it's out of date. Are there any other methods of finding this out?Slype
@Slype Can you share the relevant snippet from your log?Kalliekallista
You made my day. In my case, some deleted files were still referenced in the Solution Explorer (though unused). Important to look for "not up to date", as the log is huge.Overuse
@RyanLundy I had a similar issue. But sometimes I WANT to revert the .ico file to an older version. In that case "Copy if newer" won't notice this. Is there any way to "Copy if different"?Amalgamate
@Amalgamate in such cases run a clean first, this will delete output and a new build will copy all files regardless of modified date.Kalliekallista
@Kalliekallista Then that lose the point. It's equivalent to rebuild, and it takes time. All I want is if it's possible to build difference(older or newer) by pressing "F5", instead of "rebuild". I guess there is simply no "Copy if different".Amalgamate
@Amalgamate That's right, there's no "Copy if different option", and this is consistent with how cs files are handled. I.e. if your source control is set to preserve source control time and a cs file is reverted VS will not compile that file unless a clean or rebuild is done. These are exceptional cases, normally the only change is forward in time. Until such option will be implemented you can use pre or post-build events where you can use robocopy or other copy method of your choice.Kalliekallista
L
18

While I don't think this is a fix, it is a workaround that has worked for my situation...

I originally had about 5 projects out of 50 that contained a Resources section. These projects would always be rebuilt and thus anything that they depended on would also be rebuilt. One of those 5 projects was a "base" level library that 48 of the other projects referenced, thus 96% of my project would be rebuilt every time even if it didn't need it.

My workaround was to use dependency injection, interfaces, and a dedicated "Resources" project. Instead of having those 5 projects reference their own Resources object, I created an interface in each project that would supply the desired resources. Then, the classes that needed those resources would require that interface be passed in during their creation in the constructor (constructor injection).

I then created a separate "Resources" project that had an actual Resources section like normal. This project only contained the resources themselves, and a class for each interface that was needed to provide those resources via an interface. This project would reference every other project that had a resource dependency and implement the interface that the project needed.

Finally, in my "Top Level" project which nothing referenced (and where the exe was actually built and my composition root lives) I referenced the "Resources" project, wired up the DI, and away we went.

This means that only two projects (the "Resources" and the "Top Level") will be rebuilt every time, and if I do a partial build (Shift-F6) then they won't get rebuilt at all.

Again, not a great work around, but with 48 projects being built every time a build would take about 3 minutes, so I was losing 30 to 90 minutes a day with needless rebuilds. It took awhile to refactor, but I think it was a good investment.

Here is a simplified diagram. Note that the dependencies from Main.exe to Proj1 and Proj2 are not shown in order to reduce clutter.

Diagram of solution

With this design, I can do a build of Proj1 or Proj2 without triggering a full rebuild, since they don't have any dependencies on a Resources section. Only Main knows about the Resources implementation.

Laski answered 27/2, 2013 at 20:30 Comment(0)
Z
17

This happens when a project has a file that doesn't really exist.
The project can't determine if the file was changed (because it's not there) so it rebuilds.

Simply look at all the files in the project, and search for the one that doesn't have an expandable arrow near it.

Zoniazoning answered 28/4, 2014 at 12:8 Comment(3)
This was my problem too, however in my case there was an expandable arrow next to it as the file had been deleted recently. So you might have to look a bit more carefully to find the deleted file causing the relink.Whizbang
What if I have 7 thousand million files?Dicot
You can create a little script/program that goes over the project file or the .filter file and check that the referenced files exist.Zoniazoning
C
11

I had the same issue in VS 2015.

What did the trick for me is:

  1. One project was referencing itself copy in some other project bin (magic, yes). This kind of stuff could be found when switching to diagnostic build output (in build options) and then trying to build projects one by one from the top of projects hierarchy - if you see the project that rebuilds even if nothing has been changed then see it's references.
  2. I've changed all "copy always" files in all projects to "copy if newer". Basically, in all .csproj files replace <CopyToOutputDirectory>Always</CopyToOutputDirectory> to <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
  3. Then I've disabled NTFS tunneling as described in this article with this powershell script:

New-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem" -Name "MaximumTunnelEntries" -Value 0 -PropertyType "DWord"

After that I needed on rebuild and it seems working for now.

Canova answered 20/3, 2016 at 19:31 Comment(1)
Is there a quick way to do this (e.g. some specific text I can search through)? I'm facing the same issue in VS 2015 and I have a fairly large solution file (including some projects I'm not allowed to modify because they don't "belong" to me).Lubra
E
5

In my case the culprit was "Copy Local" setting of a referenced dll set to true and "Copy to Output Directory" setting a file set to Copy always.

Ehtelehud answered 27/11, 2015 at 5:38 Comment(0)
T
5

For .Net Core Projects, all solutions above are not working. I've found the solution. In case you are using Visual Studio 2019:

  1. Build the solution twice
  2. Turn on Tools -> Options -> Projects and Solutions -> SDK-Style Projects -> Logging Level -> Verbose
  3. Clear the output window
  4. Build your start project
  5. Inspect the output window. All the string starting with FastUpToDate
  6. You will find some project items that are making your project not up to date.
  7. Fix these issues and try again from step 1. If your fixes are correct, you will achieve Build: 0 succeeded, 0 failed, {n} up-to-date, 0 skipped in the last string of build output.
Thuja answered 29/11, 2020 at 12:57 Comment(1)
Made simple script now printing missing files (C++ project) #24063694Alisonalissa
R
3

The MSBuild team is collecting documentation about investigating build incrementality issues here: https://github.com/Microsoft/MSBuild/wiki/Rebuilding%20when%20nothing%20changed

UPDATED LINK: https://github.com/dotnet/msbuild/blob/main/documentation/wiki/Rebuilding-when-nothing-changed.md

Rickrickard answered 15/2, 2017 at 19:48 Comment(1)
Really useful link. Saw your tool mentioned over there as well, really nice work on that! I'll probably take a stab at it to debug one of our solutions.Forefoot
U
2

Another problem that frequently happens is when some item in your solution has a modified stamp that is in the future. This can happen if you set your clock forward, and then set your clock to the correct time. I had this happen while installing Linux.

In this case you can recursively touch all the files using git bash (yes, in Windows):

find . -exec touch {} \;
Underslung answered 10/2, 2017 at 5:0 Comment(0)
D
2

I had this same problem and it turned out to be related to a couple of project that had a copy local reference to a dll in their own output directory.

The key to finding this was having diagnostic output set for the build output, but also knowing what to look for in the log. Searching for: 'not up to date' was the key.

Derek answered 13/9, 2018 at 20:36 Comment(0)
B
1

Here is an answer from VS2010 always rebuilds solution?

This issue is solved by changing the project files, cleaning solution, deleting all bin folders by hand, restarting Visual studio and rebuilding everything.

Beautiful answered 17/2, 2013 at 1:1 Comment(1)
I'm not sure what 'changing the project files' meant, but I gave the rest of it a shot with no effect. It appears like it may be related to a resource file (see added info to question)Laski
A
1

Based on your observations, it sounds like you have projects expressing dependencies to other projects in a way that isn't obvious. It is possible for orphaned dependencies to remain in project files without being apparent in the UI. Have you looked through a misbehaving project file after opening it in a text editor? Checked solution build dependencies?

If you're not able to spot anything, try recreating one of your projects from scratch to see if the new project exhibits the same problem. If the clean project builds correctly, you'll know that you have unwanted dependencies expressed somewhere. As far as I know, these would have to be in the project file(s) or the solution file, unless you have makefiles or other unusual build steps.

Apposition answered 17/2, 2013 at 3:37 Comment(4)
After some extensive research, it appears like a Resources.resx may be the cause of this behavior. I added info to my question to describe my experiments.Laski
It's not clear from your new information to which project you added the .resx file. In any case, be careful when testing that you manually remove all build-created folders between tests to ensure that leftover files from earlier don't affect later tests.Apposition
The results are curious, but unfortunately I don't have anything new to add other than I would continue to narrow the problem down to the bare minimum (only two projects instead of three, only new unmodified wizard created projects with the minimum required changes to reproduce the problem, etc.) then see if someone else can reproduce the problem with the same project files. If they can, submit a bug report via Microsoft Connect.Apposition
My apologies for not including which project I was tweaking. I've updated the statement to show that I was modifying the resource file of the lowest (B) project. I'll continue exploring this since I probably lose 1 hour a day waiting on needless rebuilds.Laski
V
1

I've finally found one more culprit that I had hard time finding by increasing the build log verbosity.

In some cases, MSBuild looks for vc120.pdb in the output folder, and if this file doesn't exist, it will rebuild the entire project. This occurs even if you have disabled debug symbol generation.

The workaround here is to enable debug symbols and let this file get generated, then disable the setting again without deleting the PDB file.

Vasiliki answered 19/3, 2018 at 1:9 Comment(2)
How would this option scale in a team using source control? Would you check-in the PDB file into the source (that sounds bad)?? Otherwise, whenever someone gets the project fresh they'd need to perform this manual step.Forefoot
@julealgon: no clue :/Vasiliki
A
0

I had the same issues with you. I found that it came from some deleted files. When I had removed the files from my project, the issues was gone. Regards.

Assyriology answered 26/1, 2015 at 13:58 Comment(0)
N
0

For this category of build problems setting MSBuild output verbosity to 'diagnostic' is indeed a necessary first step. Most of the time the stated reason for the re-builds would be enough to act upon, BUT occasionally MSBuild would erroneously claim that some files are modified and need to be copied.

If that is the case, you'd need to either disable NTFS tunneling or duplicate your output folder to a new location. Here it is in more words.

Necaise answered 16/8, 2015 at 17:58 Comment(0)
G
0

I had the problem of Visual Studio rebuilding projects when upgrading from Visual Studio 2015 to 2017 and I add this answer for the benefit of those who might experience similar problems, as it does not seem to be documented anywhere.

In my case, the problem was that all projects in the solution had the same intermediate Output path (obj). The file GeneratedInternalTypeHelper.cs gets generated by all projects containing XAML. Up to Visual Studio 2015, the build process apparently did not check for the file date of this file and thus no problem with it occurred. With VS2017 the file date of this file is checked and because a later project in the build process will overwrite it (with the same content), the earlier project will re-build, re-triggering the later build, ad infinitum.

The solution in this case is to ensure that all projects have differing intermediate output directories, which will make the problem go away.

Garlandgarlanda answered 12/6, 2018 at 9:57 Comment(0)
C
0

In my case (mixed C#, C++/CLI and native C++ solution) , some C++ projects were being re-linked even if nothing had changed. I spent ages trying to work out what was happening. In the end I worked out from the "Command Line" option that the PDB output path (option /Fd) could not handle the folder setting $(IntDir). I removed that - an empty value will do the default correctly - and my issue went away.

Claudicant answered 17/6, 2019 at 8:31 Comment(0)
T
0

As others have noticed, a likely reason is that CopyToOutputDirectory is set to Always. This can be fixed simultaneously in all project files by applying the powershell script below:

$folder = "C:\My\Solution\Folder"
$csvFiles = Get-ChildItem $folder *.csproj -rec
foreach ($file in $csvFiles)
{
    (Get-Content $file.PSPath -Encoding UTF8 -Raw) |
    Foreach-Object { $_ -replace "<CopyToOutputDirectory>Always</CopyToOutputDirectory>", "<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>" } |
    Set-Content $file.PSPath -Encoding UTF8 -NoNewline
}
Thunderbolt answered 5/11, 2019 at 9:45 Comment(0)
R
0

Files that do not exist are a problem and obviously files producing no output as well. That can happen, wenn you have a resource file in a static library. (C++)

Raeannraeburn answered 7/12, 2022 at 13:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.