2012-09-13 16 views
8

Ho scritto un file di progetto MSBuild che cercano di costruire in parallelo tutte le configurazioni della mia soluzione VS2010:MSBuild: parallelamente costruisce e .Net proietta

<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> 

E mi lancio msbuild con:

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

Il problema è che la mia soluzione ha molti progetti .Net che hanno tutti la stessa cartella di output. Questi progetti utilizzano anche gli stessi assembly esterni.

Molto spesso, due file eseguibili di output vengono generati allo stesso tempo e le loro dipendenze vengono copiate contemporaneamente. Questo porta a errori come:

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. 

che credo significa: "2 progetti diversi uso NLog e cerco di copiare il suo assemblaggio nella cartella di output, allo stesso tempo" ...

C'è un modo per aggirare questo? Mi piacerebbe davvero evitare di modificare tutti i progetti nella soluzione.

Esaminare il codice sorgente dell'attività "C: \ Windows \ Microsoft.NET \ Framework \ v4.0.30319 \ Microsoft.Common.targets (3001,9)", ho visto che è possibile eseguire nuovamente msbuild la copia:

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

ho cerco di impostare le variabili CopyRetryCount, CopyRetryDelayMilliseconds, ... speravo che se la copia non riesce, un'altra copia fatto pochi millisecondi in seguito avrebbe avuto successo. Ma non sono stato in grado di impostare questi parametri. Come posso cambiarli?

C'è un'altra soluzione?

+0

State costruendo NLog come parte del vostro prodotto o è appena stato controllato nel controllo del codice sorgente? Se lo stai costruendo, è possibile che alcuni dei tuoi progetti facciano riferimento alla posizione binaria anziché al progetto? –

risposta

3

ho trovato la soluzione

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

Funziona come previsto, ma ora si genera un avviso prima di riprovare 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 il mio ultimo test, ha generato 36 volte questo avvertimento! C'è un modo per sopprimere l'avviso MSB0326?

0

In generale, tutto ciò che viene eseguito durante la creazione non deve acquisire un blocco esclusivo sui suoi input, ma solo un blocco di lettura condivisa. Sembra che qualcosa nel processo di compilazione (probabilmente NLog, qualunque esso sia) violi questo - richiede un blocco esclusivo sull'ingresso "xxx\NLog.dll", quindi quando un altro nodo msbuild tenta di copiare lo stesso input fallisce.

Riprovare è una soluzione ragionevole per il particolare sintomo che si ha - anche se non è garantito avere sempre successo.

0

Ho avuto lo stesso problema. Avevo bisogno di aggiungere un'adeguata eccezione al mio AntiVirus per evitare DLL sacanning prodotte da MsBuild.

Problemi correlati