views:

1989

answers:

6

Hello. I maintain the build of a fairly large piece of software, consisting of roughly 350 csharp projects. Our build time for a debug built clocks in at about 17 minutes.

I have been looking at ways to improve build time, and the BuildInParallel property did look intriguing. Especially since we have a quad-core server doing our builds, it should really be able to take advantage of the computing power.

But alas... After setting the property, modifying the config file for the build agent and restarting it, the first run really did look promising, way faster than normal, right up until the point where it failed.

After looking at the build logs, it looks like the build fails when it attempts to copy references marked as CopyLocal=true to the ouput dir. If C# project A and C# project B are built in parallel, and the both reference the same third-party dll, and tries to copy it at the same time, the second process to attempt to copy the file will get a file access violation - the file is being used by another process.

Anyone experienced this, and been able to get multi-proc builds working on Team Build?

A: 

Yep, sure thing. Here's one of the failures, kind of hard to figure out which other project was being built at the same time.

I have removed all the non-relevant stuff:


54>Target "_CopyFilesMarkedCopyLocal" in file "c:\WINDOWS\Microsoft.NET\Framework\v3.5\Microsoft.Common.targets" from project "d:\temp\PCM\1.3-Maint_CI\Sources\Modules\Core\Test\UnitTest\TestDIPS.Core.Data.Server.NUnit\TestDIPS.Core.Data.Server.NUnit.csproj": 54>Task "Copy" Copying file from "..........\Bin\3rdParty\Oracle\Oracle.DataAccess.dll" to "d:\temp\PCM\1.3-Maint_CI\Binaries\Debug\Oracle.DataAccess.dll". Command: copy /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): error MSB3021: Unable to copy file "..........\Bin\3rdParty\Oracle\Oracle.DataAccess.dll" to "d:\temp\PCM\1.3-Maint_CI\Binaries\Debug\Oracle.DataAccess.dll". The process cannot access the file 'd:\temp\PCM\1.3-Maint_CI\Binaries\Debug\Oracle.DataAccess.dll' because it is being used by another process. Done executing task "Copy" -- FAILED. 54>Done building target "_CopyFilesMarkedCopyLocal" in project "TestDIPS.Core.Data.Server.NUnit.csproj" -- FAILED.

epaulsen
A: 

Which compiler are you using? As far as I know, up until VS2005 parallel build doesn't work for multiple projects. It's a known issue that MS keeps saying they'll fix eventually, but I have no idea whether or not they actually solved it in VS2008.

Tal Pressman
We're fully on TFS2008, both clients and buildserver
epaulsen
+1  A: 

It looks like that your projects are configured to the same output directory. If you configure Project A and Project B to output to different directories, this would resolve this error.

Hamid Shahid
Yes, but this is the default behavior for TeamBuild, and I don't want to change it if there is no other way to get around it.
epaulsen
+5  A: 

The default targets that ship with MSBuild are designed for CopyLocal behavior - which is what VS relies on. CopyLocal is problematic when you're outputting to a single output directory.

To be able to truly build in parallel, you'll need to disable several CopyLocal specific behaviors in the Microsoft.*.Common.*.targets files. I've spoken with some folks in the MSBuild team in the past, and this is a particularly hairy thing to do. Even if you do blank-out some of the CopyLocal behavior, the VS test accessors don't behave well with build in parallel.

Some of the things you can start with:

  1. Disable CopyLocal behavior for references by setting private to true.
  2. Disable CopyLocal for CopyToOutputPath files when building dependent Projects.
gokult
Sorry for the late response, but thank you so much for the clarifying answer.Your answer is in line with my latest findings, I had problems with the test accessors. I found that I would have to either banish test accessors or modify the targets file, which is something that we do not want to do.Hopefully this will be fixed in Team Build 2010 / .Net 4.0
epaulsen
+1  A: 

Hi,

I have the same problem many months ago.

There are two types of file copy in VS C# project files (.csproj files):

  1. Referenced Assemblies which has a "Copy Local" property. when the property is True, the assembly is copied into output path.

  2. Additional files which has a "Copy to Output Directory" property. when the property is set to "copy always" or "copy if newer" the file is copied into output path.

problem:

A: If tow or more projects are built concurrently, and two of them tries to copy the same file into output directory, you may faced with the errors like "error MSB3021: Unable to copy file", "Access to the path is denied", "The process cannot access the file", etc.

B: If two or more projects refrences a common project which has some items of type 2. In this case during the parallel build of the projects, two of them may tries to build the "GetCopyToOutputDirectoryItems" target of the common project concurrently. So you may again faced with the above exceptions.

solution:

Step1: The solution is to set the property of common Items (to False in case 1 and to "dont copy" in case 2) for all but one of these common items in your projects. or remove them If it is possible.

In order to find potential mistakes, you can search the words "private" (for case 1) and "CopyToOutputDirectory" (for case 2) in files *.csproj

Step2: ...

Good Luck

Shahyad Sharghi