2011-05-23 46 views
7

我試圖加快我們的構建(csharp,msbuild,.net 3.5)。用fsutil硬鏈接創建替換副本。加快msbuild與fsutil硬鏈接創建而不是慢速複製任務

此前,我幾乎通過在sln文件上運行腳本並使dll引用private = false,然後使用post build事件創建硬鏈接。問題是傳遞依賴不包括在內。所以,我想我需要參考msbuild中的ResolveAssemblyReference任務來獲取我需要的傳遞依賴關係。

任何想法?

This人試過同樣的事情,但沒有發佈最終的解決方案。

要清楚:我想要的是保持單獨的bin目錄,而不是將文件從一個拷貝到另一個,以創建從源文件(引用或依賴項)到目標文件的硬鏈接(當前項目的倉)。這要快得多,並且與複製具有幾乎相同的效果。

+1

爲什麼不成立一個DEVPATH所有的bin文件夾中,而不是。那麼除了關閉copylocal之外,你不需要做任何事情。 http://blogs.msdn.com/b/junfeng/archive/2005/12/13/503059.aspx – adrianm 2011-06-08 12:18:42

回答

6

這在VS 2010中受支持。但不是2008.請參閱UseHardLinksIfPossible選項在_CopyFilesMarkedCopyLocal中複製。

另請參閱http://social.msdn.microsoft.com/Forums/en/tfsbuild/thread/9382a3d8-4632-4826-ad15-d5e845080981http://msdn.microsoft.com/en-us/library/ms171466(v=VS.90).aspx上下文。

覆蓋_CopyFilesMarkedCopyLocal目標。我們在底部的csproj文件中添加如下內容:<Import Project="..\..\..\..\..\\CommonBuild\TW.Override.Microsoft.Common.targets" />(這是自動添加到文件中的,每個完整版本都有一個nant任務,因此每個項目都有好處)。

我們新的目標文件是:

 
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> 
    <UsingTask TaskName="CopyWithHardlinkOption" AssemblyFile="..\lib\TWBuildOptimization\TW.Hardlinker.dll" /> 
    <!-- 
    ============================================================ 
             _CopyFilesMarkedCopyLocal 
    Overridden in order to allow hardlinking with our custom Copy Task.           

    Hardlinking is a major performance improvement. Sometimes 50% of the time compared to copying. 

    Copy references that are marked as "CopyLocal" and their dependencies, including .pdbs, .xmls and satellites. 
    ============================================================ 
    --> 
    <Target 
     Name="_CopyFilesMarkedCopyLocal"> 
     <CopyWithHardlinkOption 
      SourceFiles="@(ReferenceCopyLocalPaths)" 
      DestinationFiles="@(ReferenceCopyLocalPaths->'$(OutDir)%(DestinationSubDirectory)%(Filename)%(Extension)')" 
      SkipUnchangedFiles="true" 
       UseHardlinksIfPossible="true" 
      OverwriteReadOnlyFiles="$(OverwriteReadOnlyFiles)"> 
      <Output TaskParameter="DestinationFiles" ItemName="FileWritesShareable"/> 
     </CopyWithHardlinkOption> 
    </Target> 
</Project> 

見的MSBuild 4複製UseHardlinksIfPossible選項。我通過反編譯和重新實現將它支持到3.5。在CopyFileWithLogging相關的邏輯是:

 // The port from 4.0's task that allows hardlinking 
     bool hardlinkSucceeded = false; 
     if (UseHardlinksIfPossible) 
     { 
      if (File.Exists(destinationFile)) 
      { 
       FileUtilities.DeleteNoThrow(destinationFile); 
      } 
      if (!TwNativeMethods.CreateHardLink(destinationFile, sourceFile, IntPtr.Zero)) 
      { 
       var win32Exception = new Win32Exception(Marshal.GetLastWin32Error()); 
       Log.LogMessage(MessageImportance.High, "Hardlinking had a problem {0}, will retry copying. {1}", new object[] {win32Exception.Message, win32Exception}); 
      } 
      hardlinkSucceeded = true; 
     } 
     if (!hardlinkSucceeded) 
     { 
      Log.LogMessageFromResources(MessageImportance.Normal, "Copy.FileComment", new object[] { sourceFile, destinationFile }); 
      Log.LogMessageFromResources(MessageImportance.Low, "Shared.ExecCommand", new object[0]); 
      Log.LogCommandLine(MessageImportance.Low, "copy /y \"" + sourceFile + "\" \"" + destinationFile + "\""); 
      File.Copy(sourceFile, destinationFile, true); 
     } 
     // end port 

也不得不添加這些:

// decompiled from 4.0 
internal static class TwNativeMethods 
{ 
    [DllImport("kernel32.dll", CharSet=CharSet.Unicode, SetLastError=true)] 
    internal static extern bool CreateHardLink(string newFileName, string exitingFileName, IntPtr securityAttributes); 
} 

// decompiled from 4.0 
internal static class FileUtilities 
{ 
    internal static void DeleteNoThrow(string path) 
    { 
     try 
     { 
      File.Delete(path); 
     } 
     catch (Exception exception) 
     { 
      if (ExceptionHandling.NotExpectedException(exception)) 
      { 
       throw; 
      } 
     } 
    } 
} 

// decompiled from 4.0 
internal static class ExceptionHandling 
{ 
    // Methods 
    internal static bool IsCriticalException(Exception e) 
    { 
     return (((e is StackOverflowException) || (e is OutOfMemoryException)) || ((e is ExecutionEngineException) || (e is AccessViolationException))); 
    } 

    internal static bool NotExpectedException(Exception e) 
    { 
     return (((!(e is UnauthorizedAccessException) && !(e is ArgumentNullException)) && (!(e is PathTooLongException) && !(e is DirectoryNotFoundException))) && ((!(e is NotSupportedException) && !(e is ArgumentException)) && (!(e is SecurityException) && !(e is IOException)))); 
    } 

    internal static bool NotExpectedReflectionException(Exception e) 
    { 
     return ((((!(e is TypeLoadException) && !(e is MethodAccessException)) && (!(e is MissingMethodException) && !(e is MemberAccessException))) && ((!(e is BadImageFormatException) && !(e is ReflectionTypeLoadException)) && (!(e is CustomAttributeFormatException) && !(e is TargetParameterCountException)))) && (((!(e is InvalidCastException) && !(e is AmbiguousMatchException)) && (!(e is InvalidFilterCriteriaException) && !(e is TargetException))) && (!(e is MissingFieldException) && NotExpectedException(e)))); 
    } 
} 
+0

有沒有辦法強制msbuild將文件(或創建硬鏈接)從\ obj \ debug移動到\ bin \ debug而不是複製? – ya23 2011-08-26 14:56:14

+0

@ ya23我猜\ dob \目錄下的\ obj和\ bin不一樣。 – Ankush 2011-10-19 12:39:19

0

您是否嘗試過定義在ResolveAssemblyReferences目標之後運行的自己的目標? ResolveAssemblyReferences運行後,您應該能夠使用@(ReferencePath)項目來驅動鏈接創建。考慮實施AfterResolveReferences,它在Microsoft.Common.targets中只是一個空的佔位符供您重寫。

+0

謝謝,最後我超過了MsBuild的複製本地任務來創建硬鏈接,而不是複製引用的傳遞閉包。我希望能夠幫助其他人開源。並計劃發佈更詳細的回覆並標記回答的問題。 – JAWspeak 2011-06-03 05:49:46