The time it takes to build your solution in Visual Studio could greatly hinder your performance. Especially if you got to some trial and error desperate measures which let's face it - everyone has to do from time to time.
Let's start with our experience. Few years back in SItefinity we managed to reduce the build times of the Telerik.Sitefinity.sln several times with some simple changes. When the solution started to rapidly grow on project numbers we noticed that the build times increase exponentially. Digging a bit got us to a bottleneck that once sorted out gave us improved build times by 5 minutes. Of course those times could be very different on your solution depending on its size the hardware you are using etc.
|Optimization ||Build time ||Rebuild time |
|No ||~3 min 30 sec ||~6 min 50 sec |
|Yes ||~1 min 30 sec ||~1 min 50 sec |
We achieved this by avoiding a lot of unnecessary .dll copy operations during the build. Those copy operations occur due to a setting on a project reference or assembly reference called CopyLocal.
By default all project references have their CopyLocal property set to true. If “Project A” references “Project B” and the reference is set to CopyLocal=true all output from “Project B” (dlls, pdbs, XML) will be copied to the output directory of “Project A”.
Here is a visual representation:
We had to change 2 things to avoid this:
- We changed all projects inside Telerik.Sitefinity.sln so that all their project references’ copy local setting is defaulted to false. This is done only if the build is inside Visual Studio as it causes missing dlls in the _PublishedWebSites folder when the build is invoked with msbuild and specific OutDir (publishing). The MSBuild targets file that we added to all .csproj files can be found on the bottom of the post.
- We changed the output of all projects that SitefinityWebApp depends on to be the SitefinityWebApp/bin folder and not their own bin/ folders.
- We changed all dll references CopyLocal values to false.
Here a visual representation of the process after the change:
As you can see this is a much more fragile setup as it requires a manual settings for each new added project but I am sure you will agree this is an acceptable trade-off.
Another conclusion that can be made is that this setup will not work for solutions that have multiple starting projects like multiple websites, console applications, desktop apps etc. In this case another step will be required for example on after build that will take the resulting dlls from a specified folder and copy them to the startup projects.
Here is the ProjectReferenceModifier.targets that we wrote and included in every .csproj file of the solution:
<!--Set the copy local for project references to False only if the build is Inside Visual Studio or no OutDir was specified.-->
"$(BuildingInsideVisualStudio)=='True' OR ($(OutDirWasSpecified)!='True' AND $(WebProjectOutputDirInsideProject)!='True')"