Visual Studio Optimizing Build Speed Only Locally
The scenario is this one:
We need to reduce the time of building a solution that contains several projects. We have the constraint that we cannot consolidate projects, thus we are having around 50 projects. The build time at this moment is around 3 minutes. A quick test by setting manually all project references property CopyLocal to False and changing the output directory to a central one improved the building performance by more than 50%. However, the problem is by doing so, when we deploy or run out test on CI, DLLs are missing (I suspect it builds by using the main project and not all projects of the solution).
I thought that I can have 2 sets of build directives. One when developing that will set CopyLocal to false and output into a single directory all DLL, and one when deploying in the CI and Azure website (which preserve the normal DLL location).
I have read in previous post and here that is it possible to the CopyLocal with MsBuild by using a target file (not sure yet about the output directory). Thus, I could have this one use the targets file on the local machine and not when deploying.
My question is how can I have Visual Studio's Build action to use a specific targets file when developing and not when deploying with the IDE to Azure or the CI environment?
You can use a itemgroup with a condition to optionally override the output directory. Or use it to remove the copy-local flag from your Reference items. The same trick works for ProjectReferences.
Then make this group conditional using a number of flags:
IsDesktopBuild Is true for a build that's running outside of a build server BuildingInsideVisualStudio Is true for a build that's running inside VS
Putting it all together:
<Target Name="BeforeBuild" Condition="'$(IsDesktopBuild)' != 'true'"> <ItemGroup> <ProjectReferenceNew Include="@(ProjectReference)"> <Private>False</Private> </ProjectReferenceNew> <ProjectReference Remove="@(ProjectReference)"/> <ProjectReference Include="@(ProjectReferenceNew)"/> </ItemGroup> <ItemGroup> <ReferenceNew Include="@(Reference)"> <Private>False</Private> </ReferenceNew> <Reference Remove="@(Reference)"/> <Reference Include="@(ReferenceNew)"/> </ItemGroup> </Target>
To improve performance of this translation, you'll want to specify the Input and Output parameters of the Target:
<Target Name="BeforeBuild" Condition="'$(IsDesktopBuild)' != 'true'" Inputs="@(Reference);@(ProjectReference)" Outputs="@(Reference);@(ProjectReference)" > .... </Target>