MsBuild 4.0 added the new attribute "UseHardlinksIfPossible" to the Copy task. Using Hardlinks makes your build faster because less IO operations and disk space is needed (= better usage of file system cache). What's best is that this new option is already be used by the standard .net build system! But Microsoft decided to turn them off by default.
After searching a little bit in the c# target files I found out how to turn this feature globally on and my build was 20% faster than before. And if you have big builds with more than a hundred projects this counts!
So here comes the way to turn on hard linking in your build. First, this works only with NTFS. Second you have to explicitly set the ToolsVersion to 4.0. You can do this with a command line argument (msbuild /tv:4.0) or inside the project file (<Project DefaultTargets="Build" ToolsVersion="4.0" ...).
Then you have to override the following properties with a value of "True":
- CreateHardLinksForCopyFilesToOutputDirectoryIfPossible
- CreateHardLinksForCopyAdditionalFilesIfPossible
- CreateHardLinksForCopyLocalIfPossible
- CreateHardLinksForPublishFilesIfPossible
Use command line properties (msbuild /p:CreateHardLinksForCopyLocalIfPossible=true) to override them for all projects in one build. Or you can create a little startup build file that collects all projects and set the properties in one place. Here is mine:
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" >
<PropertyGroup>
<Include>**\*.csproj</Include>
<Exclude>_build\**\*.csproj</Exclude>
<CreateHardLinksIfPossible>true</CreateHardLinksIfPossible>
</PropertyGroup>
<ItemGroup>
<ProjectFiles Include="$(Include)" Exclude="$(Exclude)"/>
</ItemGroup>
<Target Name="Build" >
<MSBuild Projects="@(ProjectFiles)" Targets="Build" BuildInParallel="True" ToolsVersion="4.0"
Properties="Configuration=$(Configuration);
BuildInParallel=True;
CreateHardLinksForCopyFilesToOutputDirectoryIfPossible=$(CreateHardLinksIfPossible);
CreateHardLinksForCopyAdditionalFilesIfPossible=$(CreateHardLinksIfPossible);
CreateHardLinksForCopyLocalIfPossible=$(CreateHardLinksIfPossible);
CreateHardLinksForPublishFilesIfPossible=$(CreateHardLinksIfPossible);
" />
</Target>
</Project>
Nice - I'll give that a try soon.
ReplyDeleteIt seems to me that all of this only works when building with MSBuild directly (e.g. invoking msbuild via command line), and not when building within Visual Studio.
ReplyDeleteI mean, it seems that Mircosoft deliberately disabled the option to set any of these "CreateHardLinks..." properties to True when building inside Visual Studio:
""
(Microsoft.Common.targets)
The empty quotes above should read:
Delete"By default we're not using Hard Links to copy to the output directory, and never when building in VS"