27

我维护了一个相当大的软件的构建,包括大约 350 个 csharp 项目。我们调试内置时钟的构建时间大约为 17 分钟。

我一直在寻找缩短构建时间的方法,而 BuildInParallel 属性看起来确实很有趣。尤其是因为我们有一个四核服务器在做我们的构建,它应该真的能够利用计算能力。

但是唉......在设置属性,修改构建代理的配置文件并重新启动它之后,第一次运行看起来确实很有希望,比正常速度快得多,直到它失败了。

查看构建日志后,当它尝试将标记为 CopyLocal=true 的引用复制到输出目录时,构建似乎失败了。如果 C# 项目 A 和 C# 项目 B 是并行构建的,并且两者都引用相同的第三方 dll,并尝试同时复制它,则尝试复制文件的第二个进程将获得文件访问冲突 -该文件正被另一个进程使用。

任何人都经历过这种情况,并且能够在 Team Build 上进行多进程构建吗?


这是其中一个失败,很难弄清楚同时在建造哪个其他项目。

我已经删除了所有不相关的东西:

54>从项目“d:\temp\PCM\1.3-Maint_CI\Sources\Modules\Core\ Test\UnitTest\TestDIPS.Core.Data.Server.NUnit\TestDIPS.Core.Data.Server.NUnit.csproj”:54>任务“复制”从“..........\Bin\ 3rdParty\Oracle\Oracle.DataAccess.dll”到“d:\temp\PCM\1.3-Maint_CI\Binaries\Debug\Oracle.DataAccess.dll”。命令:复制 /y "..........\Bin\3rdParty\Oracle\Oracle.DataAccess.dll" "d:\temp\PCM\1.3-Maint_CI\Binaries\Debug\Oracle.DataAccess.dll " 54>c:\WINDOWS\Microsoft.NET\Framework\v3.5\Microsoft.Common.targets(2703,9): 错误 MSB3021: 无法复制文件 ".......\Bin\ 3rdParty\Oracle\Oracle.DataAccess.dll" 到“d:\temp\PCM\1.3-Maint_CI\Binaries\Debug\Oracle.DataAccess.dll”。该进程无法访问文件“d:\temp\PCM\1.3-Maint_CI\Binaries\Debug\Oracle.DataAccess.dll”,因为它正被另一个进程使用。完成执行任务“复制”——失败。54>在项目“TestDIPS.Core.Data.Server.NUnit.csproj”中完成构建目标“_CopyFilesMarkedCopyLocal”——失败。

4

6 回答 6

15

MSBuild 附带的默认目标是为 CopyLocal 行为而设计的——这是 VS 所依赖的。当您输出到单个输出目录时,CopyLocal 会出现问题。

为了能够真正并行构建,您需要在 Microsoft.*.Common.*.targets 文件中禁用多个 CopyLocal 特定行为。我过去曾与 MSBuild 团队中的一些人交谈过,这是一件特别麻烦的事情。即使您取消了某些 CopyLocal 行为,VS 测试访问器在并行构建时也表现不佳。

您可以从以下几点开始:

  1. 通过将 private 设置为 true,禁用引用的 CopyLocal 行为。
  2. 在构建依赖项目时禁用 CopyToOutputPath 文件的 CopyLocal。
于 2009-04-30T06:17:11.010 回答
10

MS Build Copy 任务具有未记录的功能,至少 Google 保持沉默。如果设置系统范围的环境变量 MSBUILDALWAYSRETRY=1 此任务将重试复制文件,即使它在复制操作期间出现访问被拒绝异常

输出示例

C:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.Common.targets (3513): Got System.UnauthorizedAccessException: Access to the path 'C:\Builds\8\28\Binaries\Release\fr\System.Spatial.resources.dll' is denied.
   at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
   at System.IO.File.InternalCopy(String sourceFileName, String destFileName, Boolean overwrite, Boolean checkHost)
   at System.IO.File.Copy(String sourceFileName, String destFileName, Boolean overwrite)
   at Microsoft.Build.Tasks.Copy.CopyFileWithLogging(FileState sourceFileState, FileState destinationFileState)
   at Microsoft.Build.Tasks.Copy.DoCopyWithRetries(FileState sourceFileState, FileState destinationFileState, CopyFileWithState copyFile) copying C:\Builds\8\28\Sources\Main\Solutions\packages\System.Spatial.5.2.0\lib
et40\fr\System.Spatial.resources.dll to C:\Builds\8\28\Binaries\Release\fr\System.Spatial.resources.dll and HR is -2147024891
 C:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.Common.targets (3513): Retrying on ERROR_ACCESS_DENIED because MSBUILDALWAYSRETRY = 1
 C:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.Common.targets (3513): Could not copy "C:\Builds\8\28\Sources\Main\Solutions\packages\System.Spatial.5.2.0\lib
et40\fr\System.Spatial.resources.dll" to "C:\Builds\8\28\Binaries\Release\fr\System.Spatial.resources.dll". Beginning retry 1 in 1000ms. Access to the path 'C:\Builds\8\28\Binaries\Release\fr\System.Spatial.resources.dll' is denied.
于 2013-03-23T06:34:51.570 回答
9

几个月前我也有同样的问题。

VS C# 项目文件(.csproj 文件)中有两种类型的文件复制:

  1. 具有“复制本地”属性的引用程序集。当属性为 True 时,程序集被复制到输出路径中。

  2. 具有“复制到输出目录”属性的附加文件。当属性设置为“始终复制”或“如果较新则复制”时,文件将被复制到输出路径中。

问题:

A:如果同时构建两个或多个项目,并且其中两个尝试将同一个文件复制到输出目录中,您可能会遇到诸如“错误MSB3021:无法复制文件”,“访问路径被拒绝”之类的错误、“进程无法访问文件”等。

B:如果两个或多个项目引用了具有类型2的某些项目的公共项目。在这种情况下,在项目的并行构建过程中,其中两个可能会尝试同时构建公共项目的“GetCopyToOutputDirectoryItems”目标。因此,您可能再次面临上述异常。

解决方案1:

强制不同 .csproj 文件的 OutputPath 不在同一路径中

http://social.msdn.microsoft.com/Forums/is/tfsbuild/thread/a62a6f98-ec44-46c1-a0d0-7f441f0db973

解决方案2:

第 1 步:解决方案是为项目中这些常见项目中的一个以外的所有项目设置公共项目的属性(在案例 1 中为 False,在案例 2 中为“不复制”)。或删除它们如果可能的话。

为了发现潜在的错误,您可以在文件 *.csproj 中搜索“private”(针对案例 1)和“CopyToOutputDirectory”(针对案例 2)这两个词

第2步: ...

祝你好运

于 2009-11-23T07:14:59.407 回答
1

看起来您的项目已配置到相同的输出目录。如果您将项目 A 和项目 B 配置为输出到不同的目录,这将解决此错误。

于 2009-04-23T10:49:44.593 回答
1

这也可能由于文件为只读而发生。在这些情况下(即,不是其他大部分答案所涵盖的情况),有适当的解决方法,具体取决于您是否能够依赖 MSBuild 3.5 或更高版本

于 2009-11-24T16:13:46.530 回答
0

您使用的是哪个编译器?据我所知,直到 VS2005 并行构建不适用于多个项目。这是一个已知问题,MS 一直说他们最终会解决,但我不知道他们是否真的在 VS2008 中解决了这个问题。

于 2009-04-23T01:44:47.287 回答