Did you ever feel like Visual Studio is rebuilding projects every single time, even when there were no changes to the code?

We can build, change nothing, build again and there we go… VS is starting a build instead of saying all my projects are up to date.

Also, there’s that nagging feeling that even when we do change something, VS is building way more projects that it needs.

Like most things I do in life, frustration led me to look further into this matter.

Divide and Conquer

We have two different issues here:
1) VS rebuilds projects even though they haven’t changed.
2) When something did change, VS tends to build more projects than needed.

So let’s tackle both of these issues.

VS rebuilds projects even though they haven’t changed

There are several reasons I know of that cause this phenomenon. Luckily, we can fix all them and save an extra minute 20 times a day.

The most important here to know here is how to find out the issues.

In your solution, go to Tools -> Options. Choose Projects and Solutions -> Build and Run and select Diagnostic in “MSbuild project build ouput verbosity”.

This will make the build slower but will show why there’s a need to a rebuild.

Every time there’s a need to rebuild a project, you will see this kind of message:

In the Output window we can see what is being rebuilt and why.
Here for example, we see that we have a picture with “Copy always” attribute.

Let’s go over some common problems why this can happen.

Resource is set to “Copy always”

This is the example we just saw. Copy always means just what it says, and there’s never a good reason for that. There’s an option to Copy if newer instead of “Copy always”. We can find the resource file in the Solution Explorer, press F4 to see the properties and change the “Copy to output directory” field.

Important Note: In the newer SDK-style projects, the output doesn’t show this issue. If you don’t see a reason why the project is rebuilt every time, go to the .csproj file and look for <CopyToOutputDirectory>Always</CopyToOutputDirectory>. Change to <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> and you’re done.

A reference with CopyLocal set to true, but unused in a VSIX project

I think this happens only with Visual Studio extensions (VSIX projects).

When referencing a project in an extension, there’s no need to Copy local since the VSIX file embeds everything in it. If it is set to True in the CopyLocal field (in reference properties) we might experience this problem. Simply setting CopyLocal to False solves this.

Circular dependency

Having a circular dependency in a .NET project is a bit difficult. VS prevents us from referencing a project directly. However, we can reference to a .dll file in the project’s output.

Suppose we have a project A that references project B.
In project B we can add a reference to A’s output file path(..A\bin\Debug\A.exe).

And here you go, a beautiful circular dependency. This will cause both projects to be rebuilt every time.

There’s no workaround here, we’ll have to get rid of the circular dependency.


These are the reasons I know of that cause this problem. If you encountered more reasons, please comment about them and I’ll add them to the post.

Now let’s see what we can do about that other issue.

When something did change, VS tends to build more projects than needed.

This is not just a feeling, MSBuild works in a specific way that sometimes does more work than it should. Here’s the problematic scenario:

Suppose we have a project A that references project B.
In project B we have a public function Foo() which project A uses.

If we change the signature of Foo() to Foo(int x), then A has to be built again. However, if we change the internal logic inside Foo(), there’s no reason for A to be built. Just B. But MSBuild will rebuild A anyway. (And all other projects referencing B)

I believe MSBuild simply works according to date modified. If A references B, and B was modified after A.dll was modified, then MSBuild will build A as well.

What can we do about it?

ReSharper Build supposedly solves this problem. And I believe it comes with ReSharper out of the box, no extra license required.

ReSharper Build has other cool features that will make your build much faster. I have to warn you however that I did try ReSharper Build and it didn’t work for me. It was building more quickly, but the build didn’t include my code changes, rendering it useless. More than useless since I wasted time finding that out.

I don’t want you to discourage using ReSharper Build, since my manager swears by it and maybe I had a local cache problem or something.

The silver lining here is that Microsoft are aware of this issue and claim they fixed it. It should be included in some future version of Visual Studio.

Summary

For me, those extra unnecessary build times are really annoying and I feel compelled to fix them. But it really makes sense to do it once and save time in the long run. And it’s not just time saved for you, it’s really time saved for the entire team.

Thanks for reading, and if you liked the post please share, like and comment. It feels great to see that and it will motivate me to write more 🙂