2012-09-13 24 views
8

He escrito los archivos de proyecto de MSBuild que tratan de construir en paralelo todas las configuraciones de mi solución VS2010:MSBuild: paralelamente construye y proyecta .Net

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0"> 
    <ItemGroup> 
    <BuildFile Include="$(SourceRoot)MyProject.sln" /> 
    <Config Include="Debug"> 
     <Configuration>Debug</Configuration> 
    </Config> 
    <Config Include="Release"> 
     <Configuration>Release</Configuration> 
    </Config> 
    </ItemGroup> 

    <Target Name="BuildAll" Outputs="%(Config.Configuration)"> 
    <Message Text="Start building for configuration: %(Config.Configuration)" /> 
    <MSBuild Projects="@(BuildFile)" 
      Properties="Configuration=%(Config.Configuration)" 
      Targets="Build" /> 
    </Target> 
</Project> 

Y lanzo msbuild con:

msbuild /m /p:BuildInParallel=true /t:BuildAll buildall.proj 

El problema es que mi solución tiene muchos proyectos .Net que tienen la misma carpeta de salida. Estos proyectos usan también los mismos ensambles externos.

Muy a menudo, se generan dos ejecutables de salida al mismo tiempo y sus dependencias se copian al mismo tiempo. Esto conduce a errores como:

C:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.Common.targets(3001,9): 
error MSB3021: 
Unable to copy file "xxx\NLog.dll" to "D:\src\Blackbird\shared\bin\debug\NLog.xml". The process 
cannot access the file 'xxx\NLog.dll because it is being used by another process. 

que creo que significa: "2 proyectos diferentes utilizo Nlog y tratar de copiar su montaje en la carpeta de salida al mismo tiempo" ...

¿Hay alguna manera para evitar eso? Realmente me gustaría evitar modificar todos los proyectos en la solución.

Mirando el código fuente de la tarea "C: \ Windows \ Microsoft.NET \ Framework \ v4.0.30319 \ Microsoft.Common.targets (3001,9)", he visto que es posible hacer que msbuild vuelva a intentarlo la copia:

<Copy 
    SourceFiles="@(ReferenceCopyLocalPaths)" 
    DestinationFiles="@(ReferenceCopyLocalPaths->'$(OutDir)%(DestinationSubDirectory)%(Filename)%(Extension)')" 
    SkipUnchangedFiles="$(SkipCopyUnchangedFiles)" 
    OverwriteReadOnlyFiles="$(OverwriteReadOnlyFiles)" 
    Retries="$(CopyRetryCount)" 
    RetryDelayMilliseconds="$(CopyRetryDelayMilliseconds)" 
    UseHardlinksIfPossible="$(CreateHardLinksForCopyLocalIfPossible)" 
    Condition="'$(UseCommonOutputDirectory)' != 'true'" 
    > 

he intento para establecer las variables CopyRetryCount, CopyRetryDelayMilliseconds, ... yo tenía la esperanza de que si la copia falla, otra copia hecho unos pocos milisegundos más tarde tendría éxito. Pero no he podido establecer estos parámetros. ¿Cómo puedo cambiarlos?

¿Hay alguna otra solución?

+0

¿Está construyendo NLog como parte de su producto o simplemente está registrado en el control de origen? Si lo está construyendo, ¿es posible que algunos de sus proyectos hagan referencia a la ubicación binaria en lugar del proyecto? –

Respuesta

3

he encontrado la solución

<MSBuild Projects="@(BuildFile)" 
    Properties="Configuration=%(Config.Configuration);Retries=10;RetryDelayMilliseconds=50" 
    Targets="Build" /> 

Funciona como se esperaba pero ahora se genera una advertencia antes de volver a intentar la copia

C:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.Common.targets(3001,9): 
warning MSB3026: Could not copy 
"D:\src\xxx\System.Data.SQLite.pdb" to "..\Debug\System.Data.SQLite.pdb". 
Beginning retry 1 in 50ms. The process cannot access the file 
'..\Debug\System.Data.SQLite.pdb' because it is being used by another process. 

Durante mi última prueba, que genera 36 veces esta advertencia! ¿Hay alguna manera de suprimir la advertencia MSB0326?

0

En general, todo lo que se ejecuta durante la compilación no debe adquirir un bloqueo exclusivo en sus entradas, solo el bloqueo de lectura compartida. Parece que algo en su proceso de compilación (probablemente NLog, cualquiera que sea) viola esto: requiere un bloqueo exclusivo en la entrada "xxx\NLog.dll", de modo que cuando otro nodo msbuild intenta copiar la misma entrada falla.

Reintentar es una solución razonable para el síntoma particular que tiene, aunque no se garantiza que siempre tenga éxito.

0

Tuve el mismo problema. Necesitaba agregar una excepción apropiada a mi AntiVirus para evitar el sacanning de las DLL producidas por MsBuild.

Cuestiones relacionadas