Formazione
Percorso di apprendimento
Solution Architect: Design Microsoft Power Platform solutions - Training
Learn how a solution architect designs solutions.
Questo browser non è più supportato.
Esegui l'aggiornamento a Microsoft Edge per sfruttare i vantaggi di funzionalità più recenti, aggiornamenti della sicurezza e supporto tecnico.
È possibile aggiungere determinati file da importare da MSBuild per eseguire l'override delle impostazioni predefinite delle proprietà e aggiungere destinazioni personalizzate. L'ambito di queste personalizzazioni può essere controllato a livello di cartella da dove vengono inseriti questi file.
Questo articolo illustra le personalizzazioni applicabili agli scenari seguenti:
Microsoft.Net.Sdk
Se si usano progetti C++, è anche possibile usare i metodi descritti in Personalizzare le compilazioni C++.
È possibile aggiungere una nuova proprietà a ogni progetto definendola in un singolo file denominato Directory.Build.props nella cartella radice che contiene l'origine.
Durante l'esecuzione di MSBuild, Microsoft.Common.props cerca nella struttura delle directory il file Directory.Build.props. Se ne trova uno, importa il file e legge le proprietà definite al suo interno. Directory.Build.props è un file definito dall'utente che fornisce personalizzazioni ai progetti in una directory.
Analogamente, Microsoft.Common.targets cerca Directory.Build.targets.
Directory.Build.props viene importato nelle prime fasi della sequenza di file importati, che può essere importante se è necessario impostare una proprietà usata dalle importazioni, in particolare quelle importate in modo implicito usando l'attributo Sdk
, ad esempio quando si usa .NET SDK nella maggior parte dei file di progetto .NET.
Nota
I file system basati su Linux sono sensibili alle maiuscole e minuscole. Assicurati che la combinazione di maiuscole e minuscole del nome file Directory.Build.props corrisponda esattamente, altrimenti non verrà rilevato durante il processo di compilazione.
Per ulteriori informazioni, consultare questo ticket di GitHub .
Ecco ad esempio un file directory.build.props che imposta la directory di output per tutti i progetti in una soluzione di Visual Studio. L'output di ogni progetto viene inserito sotto il proprio nome di progetto. In questo esempio, il file Directory.Build.props si trova in una cartella della soluzione, con molti progetti in sottocartelle al suo interno. La proprietà $(MSBuildProjectName)
assegna il nome di ogni progetto. Poiché il file directory.build.props viene importato in ogni progetto durante la propria compilazione, viene valutato al valore corretto per ogni singolo progetto nella soluzione.
Pulire la soluzione per rimuovere eventuali file di output precedenti.
msbuild /t:Clean SolutionName.sln
Creare un nuovo file nella radice del repository denominato Directory.Build.props.
Aggiungere il codice XML seguente al file .
<Project>
<PropertyGroup>
<OutDir>C:\output\$(MSBuildProjectName)</OutDir>
</PropertyGroup>
</Project>
Nota
La proprietà $(OutDir)
è un percorso assoluto per l'output e il suo utilizzo consente di evitare la creazione di sottocartelle per configurazioni, framework di destinazione o runtime che vengono normalmente utilizzati nei progetti .NET. Prova a utilizzare la proprietà BaseOutputPath
se desideri che le usuali sottocartelle siano create in un percorso di output personalizzato.
Eseguire MSBuild. Le importazioni esistenti del tuo progetto di Microsoft.Common.props e Microsoft.Common.targets trovano il file Directory.Build.props e lo importano. La nuova cartella di output viene utilizzata per tutti i progetti che si trovano sotto quella cartella.
Quando si cerca un file Directory.Build.props, MSBuild scansiona la struttura di directory verso l'alto dal percorso della tua cartella di progetto $(MSBuildProjectFullPath)
, fermandosi dopo aver individuato un file Directory.Build.props. Ad esempio, se il $(MSBuildProjectFullPath)
è stato c:\users\username\code\test\case1, MSBuild inizierà la ricerca in tale posizione e quindi eseguirà una ricerca verso l'alto fino a quando non trova un file Directory.Build.props, come nella struttura di directory seguente.
c:\users\username\code\test\case1
c:\users\username\code\test
c:\users\username\code
c:\users\username
c:\users
c:\
Il percorso del file di soluzione è irrilevante per Directory.Build.props.
Directory.Build.props viene importato all'inizio di Microsoft.Common.propse le proprietà definite successivamente non sono disponibili. Evitare quindi di fare riferimento a proprietà non ancora definite (e verranno valutate come vuote).
Le proprietà impostate in Directory.Build.props possono essere sostituite altrove nel file di progetto o nei file importati, pertanto è consigliabile considerare le impostazioni in Directory.Build.props specificando le impostazioni predefinite per i progetti.
Directory.Build.targets viene importato da Microsoft.Common.targets dopo l'importazione di file .targets
da pacchetti NuGet. Può quindi sovrascrivere proprietà e destinazioni definite nella maggior parte della logica di compilazione o impostare proprietà per tutti i progetti indipendentemente da ciò che impostano i singoli progetti.
Quando è necessario impostare una proprietà o definire una destinazione per un singolo progetto che esegue l'override di tutte le impostazioni precedenti, inserire tale logica nel file di progetto dopo l'importazione finale. Per eseguire questa operazione in un progetto in stile SDK, è prima necessario sostituire l'attributo in stile SDK con le importazioni equivalenti. Vedere Come usare gli SDK del progetto MSBuild.
Nota
Il motore MSBuild legge tutti i file importati durante l'analisi e prima di avviare l'esecuzione della compilazione per un progetto (incluso qualsiasi PreBuildEvent
), pertanto è previsto che questi file non vengano modificati dal PreBuildEvent
o da nessun'altra parte del processo di compilazione. Eventuali modifiche non vengono applicate fino alla chiamata successiva di MSBuild.exe o alla successiva compilazione di Visual Studio. Inoltre, se il processo di compilazione contiene molte compilazioni di progetto (come con il multitargeting o la compilazione di progetti dipendenti), i file importati, inclusi Directory.build.props, vengono letti quando viene eseguita la valutazione per ogni singola compilazione di progetto.
Si supponga di avere questa struttura di soluzione standard:
\
MySolution.sln
Directory.Build.props (1)
\src
Directory.Build.props (2-src)
\Project1
\Project2
\test
Directory.Build.props (2-test)
\Project1Tests
\Project2Tests
Potrebbe essere consigliabile avere proprietà comuni per tutti i progetti (1), proprietà comuni per progetti progetti (2-src)e proprietà comuni per progetti di test(2 test).
Per fare in modo che MSBuild unisce correttamente i file "interni" ( 2-src e 2 test) con il file "esterno" (1), è necessario tenere conto che dopo che MSBuild trova un file Directory.Build.props, interrompe l'analisi. Per continuare l'analisi e l'unione nel file esterno, inserire questo codice in entrambi i file interni:
<Import Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)../'))" />
Di seguito è riportato un riepilogo dell'approccio generale di MSBuild:
<Import...>
(illustrato in precedenza) il file "esterno" dal file "interno".O più semplicemente: il primo Directory.Build.props che non importa nulla è dove MSBuild si arresta.
Per controllare il processo di importazione in modo più esplicito, usare le proprietà $(DirectoryBuildPropsPath)
, $(ImportDirectoryBuildProps)
, $(DirectoryBuildTargetsPath)
e $(ImportDirectoryBuildTargets)
. La proprietà $(DirectoryBuildPropsPath)
specifica il percorso del file Directory.Build.props
da utilizzare; analogamente, $(DirectoryBuildTargetsPath)
specifica il percorso del file Directory.Build.targets
.
Le proprietà booleane $(ImportDirectoryBuildProps)
e $(ImportDirectoryBuildTargets)
sono impostate su true
per impostazione predefinita, pertanto MSBuild cerca normalmente questi file, ma è possibile impostarli su false
per impedire l'importazione di MSBuild.
In questo esempio viene illustrato l'uso dell'output pre-elaborato per determinare dove impostare una proprietà.
Per analizzare l'utilizzo di una determinata proprietà da impostare, è possibile eseguire MSBuild con l'argomento /preprocess
o /pp
. Il testo di output è il risultato di tutte le importazioni, incluse le importazioni di sistema come Microsoft.Common.props importate in modo implicito e qualsiasi importazione personalizzata. Con questo output, è possibile vedere dove deve essere impostata la proprietà rispetto al punto in cui viene utilizzato il suo valore.
Si supponga, ad esempio, di avere un semplice progetto app console .NET Core o .NET 5 o versione successiva e di voler personalizzare la cartella di output intermedia, in genere obj
. La proprietà che specifica questo percorso è BaseIntermediateOutput
. Se si tenta di inserirlo in un elemento PropertyGroup
nel file di progetto insieme alle varie altre proprietà già impostate, ad esempio TargetFramework
, si scoprirà quando si compila il progetto che la proprietà non ha effetto. Se si esegue MSBuild con l'opzione /pp
e si cerca l'output per BaseIntermediateOutputPath
, è possibile vedere perché. In questo caso, BaseIntermediateOutput
viene letto e usato in Microsoft.Common.props
.
È presente un commento in Microsoft.Common.props che indica che la proprietà BaseIntermediateOutput
deve essere impostata qui, prima che venga usata da un'altra proprietà, MSBuildProjectExtensionsPath
. È anche possibile notare che quando BaseIntermediateOutputPath
è impostato inizialmente, è presente un controllo per un valore preesistente e, se non definito, viene impostato su obj
.
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">obj\</BaseIntermediateOutputPath>
Quindi, questa disposizione indica che per impostare questa proprietà, deve essere specificata in un punto precedente a questo. Poco prima di questo codice nell'output pre-elaborato, è possibile osservare che Directory.Build.props
viene importato, in modo da poter impostare BaseIntermediateOutputPath
lì e verrà impostato abbastanza presto per avere l'effetto desiderato.
L'output pre-elaborato abbreviato seguente mostra il risultato dell'inserimento dell'impostazione BaseIntermediateOutput
in Directory.Build.props
. I commenti all'inizio delle importazioni standard includono il nome file e in genere alcune informazioni utili sul motivo per cui il file viene importato.
<?xml version="1.0" encoding="IBM437"?>
<!--
============================================================================================================================================
c:\source\repos\ConsoleApp9\ConsoleApp9\ConsoleApp9.csproj
============================================================================================================================================
-->
<Project DefaultTargets="Build">
<!--
============================================================================================================================================
<Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk">
This import was added implicitly because the Project element's Sdk attribute specified "Microsoft.NET.Sdk".
C:\Program Files\dotnet\sdk\7.0.200-preview.22628.1\Sdks\Microsoft.NET.Sdk\Sdk\Sdk.props
============================================================================================================================================
-->
<!--
***********************************************************************************************
Sdk.props
WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and have
created a backup copy. Incorrect changes to this file will make it
impossible to load or build your projects from the command-line or the IDE.
Copyright (c) .NET Foundation. All rights reserved.
***********************************************************************************************
-->
<PropertyGroup xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!--
Indicate to other targets that Microsoft.NET.Sdk is being used.
This must be set here (as early as possible, before Microsoft.Common.props)
so that everything that follows can depend on it.
In particular, Directory.Build.props and nuget package props need to be able
to use this flag and they are imported by Microsoft.Common.props.
-->
<UsingMicrosoftNETSdk>true</UsingMicrosoftNETSdk>
<!--
Indicate whether the set of SDK defaults that makes SDK style project concise are being used.
For example: globbing, importing msbuild common targets.
Similar to the property above, it must be set here.
-->
<UsingNETSdkDefaults>true</UsingNETSdkDefaults>
</PropertyGroup>
<PropertyGroup Condition="'$(MSBuildProjectFullPath)' == '$(ProjectToOverrideProjectExtensionsPath)'" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<MSBuildProjectExtensionsPath>$(ProjectExtensionsPathForSpecifiedProject)</MSBuildProjectExtensionsPath>
</PropertyGroup>
<!--<Import Project="$(AlternateCommonProps)" Condition="'$(AlternateCommonProps)' != ''" />-->
<!--
============================================================================================================================================
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="'$(AlternateCommonProps)' == ''">
C:\Program Files\Microsoft Visual Studio\2022\Preview\MSBuild\Current\Microsoft.Common.props
============================================================================================================================================
-->
<!--
***********************************************************************************************
Microsoft.Common.props
WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and have
created a backup copy. Incorrect changes to this file will make it
impossible to load or build your projects from the command-line or the IDE.
Copyright (C) Microsoft Corporation. All rights reserved.
***********************************************************************************************
-->
<PropertyGroup>
<ImportByWildcardBeforeMicrosoftCommonProps Condition="'$(ImportByWildcardBeforeMicrosoftCommonProps)' == ''">true</ImportByWildcardBeforeMicrosoftCommonProps>
<ImportByWildcardAfterMicrosoftCommonProps Condition="'$(ImportByWildcardAfterMicrosoftCommonProps)' == ''">true</ImportByWildcardAfterMicrosoftCommonProps>
<ImportUserLocationsByWildcardBeforeMicrosoftCommonProps Condition="'$(ImportUserLocationsByWildcardBeforeMicrosoftCommonProps)' == ''">true</ImportUserLocationsByWildcardBeforeMicrosoftCommonProps>
<ImportUserLocationsByWildcardAfterMicrosoftCommonProps Condition="'$(ImportUserLocationsByWildcardAfterMicrosoftCommonProps)' == ''">true</ImportUserLocationsByWildcardAfterMicrosoftCommonProps>
<ImportDirectoryBuildProps Condition="'$(ImportDirectoryBuildProps)' == ''">true</ImportDirectoryBuildProps>
</PropertyGroup>
<!--
Determine the path to the directory build props file if the user did not disable $(ImportDirectoryBuildProps) and
they did not already specify an absolute path to use via $(DirectoryBuildPropsPath)
-->
<PropertyGroup Condition="'$(ImportDirectoryBuildProps)' == 'true' and '$(DirectoryBuildPropsPath)' == ''">
<_DirectoryBuildPropsFile Condition="'$(_DirectoryBuildPropsFile)' == ''">Directory.Build.props</_DirectoryBuildPropsFile>
<_DirectoryBuildPropsBasePath Condition="'$(_DirectoryBuildPropsBasePath)' == ''">$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildProjectDirectory), '$(_DirectoryBuildPropsFile)'))</_DirectoryBuildPropsBasePath>
<DirectoryBuildPropsPath Condition="'$(_DirectoryBuildPropsBasePath)' != '' and '$(_DirectoryBuildPropsFile)' != ''">$([System.IO.Path]::Combine('$(_DirectoryBuildPropsBasePath)', '$(_DirectoryBuildPropsFile)'))</DirectoryBuildPropsPath>
</PropertyGroup>
<!--
============================================================================================================================================
<Import Project="$(DirectoryBuildPropsPath)" Condition="'$(ImportDirectoryBuildProps)' == 'true' and exists('$(DirectoryBuildPropsPath)')">
c:\source\repos\ConsoleApp9\Directory.Build.props
============================================================================================================================================
-->
<!-- Directory.build.props
-->
<PropertyGroup>
<BaseIntermediateOutputPath>myBaseIntermediateOutputPath</BaseIntermediateOutputPath>
</PropertyGroup>
<!--
============================================================================================================================================
</Import>
C:\Program Files\Microsoft Visual Studio\2022\Preview\MSBuild\Current\Microsoft.Common.props
============================================================================================================================================
-->
<!--
Prepare to import project extensions which usually come from packages. Package management systems will create a file at:
$(MSBuildProjectExtensionsPath)\$(MSBuildProjectFile).<SomethingUnique>.props
Each package management system should use a unique moniker to avoid collisions. It is a wild-card import so the package
management system can write out multiple files but the order of the import is alphabetic because MSBuild sorts the list.
-->
<PropertyGroup>
<!--
The declaration of $(BaseIntermediateOutputPath) had to be moved up from Microsoft.Common.CurrentVersion.targets
in order for the $(MSBuildProjectExtensionsPath) to use it as a default.
-->
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">obj\</BaseIntermediateOutputPath>
<BaseIntermediateOutputPath Condition="!HasTrailingSlash('$(BaseIntermediateOutputPath)')">$(BaseIntermediateOutputPath)\</BaseIntermediateOutputPath>
<_InitialBaseIntermediateOutputPath>$(BaseIntermediateOutputPath)</_InitialBaseIntermediateOutputPath>
<MSBuildProjectExtensionsPath Condition="'$(MSBuildProjectExtensionsPath)' == '' ">$(BaseIntermediateOutputPath)</MSBuildProjectExtensionsPath>
<!--
Import paths that are relative default to be relative to the importing file. However, since MSBuildExtensionsPath
defaults to BaseIntermediateOutputPath we expect it to be relative to the project directory. So if the path is relative
it needs to be made absolute based on the project directory.
-->
<MSBuildProjectExtensionsPath Condition="'$([System.IO.Path]::IsPathRooted($(MSBuildProjectExtensionsPath)))' == 'false'">$([System.IO.Path]::Combine('$(MSBuildProjectDirectory)', '$(MSBuildProjectExtensionsPath)'))</MSBuildProjectExtensionsPath>
<MSBuildProjectExtensionsPath Condition="!HasTrailingSlash('$(MSBuildProjectExtensionsPath)')">$(MSBuildProjectExtensionsPath)\</MSBuildProjectExtensionsPath>
<ImportProjectExtensionProps Condition="'$(ImportProjectExtensionProps)' == ''">true</ImportProjectExtensionProps>
<_InitialMSBuildProjectExtensionsPath Condition=" '$(ImportProjectExtensionProps)' == 'true' ">$(MSBuildProjectExtensionsPath)</_InitialMSBuildProjectExtensionsPath>
</PropertyGroup>
...
Formazione
Percorso di apprendimento
Solution Architect: Design Microsoft Power Platform solutions - Training
Learn how a solution architect designs solutions.