Estendere il processo di compilazione di Visual Studio
Il processo di compilazione di Visual Studio è definito da una serie di file MSBuild con estensione targets importati nel file di progetto. Uno di questi file importati, Microsoft.Common.targets, può essere esteso per consentire l'esecuzione di attività personalizzate in diversi punti del processo di compilazione. Questo articolo illustra due metodi che è possibile usare per estendere il processo di compilazione di Visual Studio:
Override di destinazioni predefinite specifiche definite nelle destinazioni comuni (Microsoft.Common.targets o i file importati).
Override delle proprietà "DependsOn" definite nelle destinazioni comuni.
Eseguire l'override di destinazioni predefinite
Le destinazioni comuni contengono un set di destinazioni vuote predefinite chiamate prima e dopo alcune delle principali destinazioni nel processo di compilazione. Ad esempio, MSBuild chiama la destinazione prima della BeforeBuild
destinazione principale CoreBuild
e della AfterBuild
destinazione dopo la CoreBuild
destinazione. Per impostazione predefinita, le destinazioni vuote nelle destinazioni comuni non eseguono alcuna operazione, ma è possibile ignorare il comportamento predefinito definendo le destinazioni desiderate in un file di progetto che importa le destinazioni comuni. Eseguendo l'override delle destinazioni predefinite, è possibile usare le attività di MSBuild per offrire maggiore controllo sul processo di compilazione.
Nota
I progetti in stile SDK hanno un'importazione implicita di destinazioni dopo l'ultima riga del file di progetto. Ciò significa che non è possibile eseguire l'override delle destinazioni predefinite a meno che non si specifichino manualmente le importazioni come descritto in Procedura: Usare gli SDK del progetto MSBuild.
Per eseguire l'override di una destinazione predefinita
Identificare una destinazione predefinita nelle destinazioni comuni di cui si vuole eseguire l'override. Nella tabella seguente è riportato l'elenco completo delle destinazioni di cui è possibile eseguire l'override in totale sicurezza.
Definire le destinazioni alla fine del file di progetto, immediatamente prima del tag
</Project>
. Ad esempio:<Project> ... <Target Name="BeforeBuild"> <!-- Insert tasks to run before build here --> </Target> <Target Name="AfterBuild"> <!-- Insert tasks to run after build here --> </Target> </Project>
Compilare il file di progetto.
La tabella seguente illustra tutte le destinazioni nelle destinazioni comuni di cui è possibile eseguire l'override in modo sicuro.
Nome di destinazione | Descrizione |
---|---|
BeforeCompile , AfterCompile |
Le attività inserite in una di queste destinazioni vengono eseguite prima o dopo il completamento della compilazione principale. La maggior parte delle personalizzazioni avviene in una di queste due destinazioni. |
BeforeBuild , AfterBuild |
Le attività inserite in una di queste destinazioni vengono eseguite prima o dopo qualsiasi altra attività nella compilazione. Nota: le destinazioni BeforeBuild e AfterBuild sono già definite nei commenti alla fine della maggior parte dei file di progetto, consentendo di aggiungere facilmente eventi di pre e post-compilazione nel file di progetto. |
BeforeRebuild , AfterRebuild |
Le attività inserite in una di queste destinazioni vengono eseguite prima o dopo il richiamo della funzionalità di base per la ricompilazione. L'ordine di esecuzione delle destinazioni in Microsoft.Common.targets è: BeforeRebuild , Clean , Build e quindi AfterRebuild . |
BeforeClean , AfterClean |
Le attività inserite in una di queste destinazioni vengono eseguite prima o dopo il richiamo della funzionalità di base per la pulitura. |
BeforePublish , AfterPublish |
Le attività inserite in una di queste destinazioni vengono eseguite prima o dopo il richiamo della funzionalità di base per la pubblicazione. |
BeforeResolveReferences , AfterResolveReferences |
Le attività inserite in una di queste destinazioni vengono eseguite prima o dopo la risoluzione dei riferimenti all'assembly. |
BeforeResGen , AfterResGen |
Le attività inserite in una di queste destinazioni vengono eseguite prima o dopo la generazione delle risorse. |
Esempio: AfterTargets e BeforeTargets
Nell'esempio seguente viene illustrato come usare l'attributo AfterTargets
per aggiungere una destinazione personalizzata che esegue operazioni con i file di output. In questo caso, copia i file di output in una nuova cartella CustomOutput. Nell'esempio viene inoltre illustrato come pulire i file creati dall'operazione di compilazione personalizzata con una CustomClean
destinazione usando un BeforeTargets
attributo e specificando che l'operazione pulita personalizzata viene eseguita prima della CoreClean
destinazione.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<_OutputCopyLocation>$(OutputPath)..\..\CustomOutput\</_OutputCopyLocation>
</PropertyGroup>
<Target Name="CustomAfterBuild" AfterTargets="Build">
<ItemGroup>
<_FilesToCopy Include="$(OutputPath)**\*"/>
</ItemGroup>
<Message Text="_FilesToCopy: @(_FilesToCopy)" Importance="high"/>
<Message Text="DestFiles:
@(_FilesToCopy->'$(_OutputCopyLocation)%(RecursiveDir)%(Filename)%(Extension)')"/>
<Copy SourceFiles="@(_FilesToCopy)"
DestinationFiles=
"@(_FilesToCopy->'$(_OutputCopyLocation)%(RecursiveDir)%(Filename)%(Extension)')"/>
</Target>
<Target Name="CustomClean" BeforeTargets="CoreClean">
<Message Text="Inside Custom Clean" Importance="high"/>
<ItemGroup>
<_CustomFilesToDelete Include="$(_OutputCopyLocation)**\*"/>
</ItemGroup>
<Delete Files='@(_CustomFilesToDelete)'/>
</Target>
</Project>
Avviso
Assicurarsi di usare nomi diversi rispetto alle destinazioni predefinite elencate nella tabella nella sezione precedente (ad esempio, la destinazione di compilazione personalizzata è denominata qui CustomAfterBuild
, non AfterBuild
), poiché tali destinazioni predefinite vengono sottoposte a override dall'importazione dell'SDK che le definisce anche. Non viene visualizzata l'importazione del file di destinazione che esegue l'override di tali destinazioni, ma viene aggiunta in modo implicito alla fine del file di progetto quando si usa il Sdk
metodo di attributo per fare riferimento a un SDK.
Eseguire l'override delle proprietà DependsOn
L'override delle destinazioni predefinite è un modo semplice per estendere il processo di compilazione, ma, poiché MSBuild valuta la definizione di destinazioni in sequenza, non è possibile impedire a un altro progetto che importa il progetto di eseguire l'override delle destinazioni già sottoposte a override. Di conseguenza, ad esempio, l'ultima destinazione AfterBuild
definita nel file di progetto, al termine dell'importazione di tutti gli altri progetti, sarà quella usata durante la compilazione.
È possibile proteggersi da sostituzioni impreviste delle destinazioni eseguendo l'override delle proprietà DependsOn usate negli DependsOnTargets
attributi in tutte le destinazioni comuni. Nella destinazione Build
, ad esempio, il valore dell'attributo DependsOnTargets
è "$(BuildDependsOn)"
. Tenere in considerazione:
<Target Name="Build" DependsOnTargets="$(BuildDependsOn)"/>
Questa parte di codice XML indica che la destinazione Build
può essere eseguita solo dopo l'esecuzione di tutte le destinazioni specificate nella proprietà BuildDependsOn
. La proprietà BuildDependsOn
è definita come segue:
<PropertyGroup>
<BuildDependsOn>
BeforeBuild;
CoreBuild;
AfterBuild
</BuildDependsOn>
</PropertyGroup>
È possibile eseguire l'override di questo valore di proprietà dichiarando un'altra proprietà denominata BuildDependsOn
alla fine del file di progetto. L'inclusione della proprietà BuildDependsOn
precedente nella nuova proprietà consente di aggiungere nuove destinazioni all'inizio e alla fine dell'elenco di destinazioni. Ad esempio:
<PropertyGroup>
<BuildDependsOn>
MyCustomTarget1;
$(BuildDependsOn);
MyCustomTarget2
</BuildDependsOn>
</PropertyGroup>
<Target Name="MyCustomTarget1">
<Message Text="Running MyCustomTarget1..."/>
</Target>
<Target Name="MyCustomTarget2">
<Message Text="Running MyCustomTarget2..."/>
</Target>
I progetti che importano i file di progetto possono eseguire l'override di queste proprietà senza sovrascrivere le personalizzazioni effettuate in precedenza.
Per eseguire l'override di una proprietà DependsOn
Identificare una proprietà DependsOn predefinita nelle destinazioni comuni di cui si vuole eseguire l'override. Nella tabella che segue è riportato un elenco delle proprietà DependsOn comunemente sottoposte a override.
Definire un'altra istanza della proprietà o delle proprietà alla fine del file di progetto. Nella nuova proprietà includere la proprietà originale, ad esempio
$(BuildDependsOn)
.Definire le destinazioni personalizzate prima o dopo la definizione della proprietà.
Compilare il file di progetto.
Proprietà DependsOn comunemente sottoposte a override
Nome della proprietà | Descrizione |
---|---|
BuildDependsOn |
Proprietà di cui eseguire l'override se si vuole inserire destinazioni personalizzate prima o dopo l'intero processo di compilazione. |
CleanDependsOn |
Proprietà di cui eseguire l'override se si vuole pulire l'output del processo di compilazione personalizzato. |
CompileDependsOn |
Proprietà di cui eseguire l'override se si vuole inserire processi personalizzati prima o dopo la fase di compilazione. |
Esempio: BuildDependsOn e CleanDependsOn
L'esempio seguente è simile all'esempio BeforeTargets
e AfterTargets
, ma mostra come ottenere funzionalità simili. Estende la compilazione usando BuildDependsOn
per aggiungere un'attività CustomAfterBuild
personalizzata che copia i file di output dopo la compilazione e aggiunge anche l'attività corrispondente CustomClean
usando CleanDependsOn
.
In questo esempio si tratta di un progetto di tipo SDK. Come accennato nella nota sui progetti in stile SDK in precedenza in questo articolo, è necessario usare il metodo di importazione manuale anziché l'attributo Sdk
usato da Visual Studio quando genera i file di progetto.
<Project>
<Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk"/>
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
<Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk"/>
<PropertyGroup>
<BuildDependsOn>
$(BuildDependsOn);CustomAfterBuild
</BuildDependsOn>
<CleanDependsOn>
$(CleanDependsOn);CustomClean
</CleanDependsOn>
<_OutputCopyLocation>$(OutputPath)..\..\CustomOutput\</_OutputCopyLocation>
</PropertyGroup>
<Target Name="CustomAfterBuild">
<ItemGroup>
<_FilesToCopy Include="$(OutputPath)**\*"/>
</ItemGroup>
<Message Importance="high" Text="_FilesToCopy: @(_FilesToCopy)"/>
<Message Text="DestFiles:
@(_FilesToCopy->'$(_OutputCopyLocation)%(RecursiveDir)%(Filename)%(Extension)')"/>
<Copy SourceFiles="@(_FilesToCopy)"
DestinationFiles="@(_FilesToCopy->'$(_OutputCopyLocation)%(RecursiveDir)%(Filename)%(Extension)')"/>
</Target>
<Target Name="CustomClean">
<Message Importance="high" Text="Inside Custom Clean"/>
<ItemGroup>
<_CustomFilesToDelete Include="$(_OutputCopyLocation)**\*"/>
</ItemGroup>
<Delete Files="@(_CustomFilesToDelete)"/>
</Target>
</Project>
L'ordine degli elementi è importante. Gli BuildDependsOn
elementi e CleanDependsOn
devono essere visualizzati dopo l'importazione del file di destinazione dell'SDK standard.
Contenuto correlato
Commenti e suggerimenti
https://aka.ms/ContentUserFeedback.
Presto disponibile: Nel corso del 2024 verranno gradualmente disattivati i problemi di GitHub come meccanismo di feedback per il contenuto e ciò verrà sostituito con un nuovo sistema di feedback. Per altre informazioni, vedereInvia e visualizza il feedback per