Integrazione dell'estendibilità e del set di strumenti del sistema di progetto di Visual Studio C++

Il sistema di progetto Visual C++ viene usato per .vcxproj file. Si basa su Visual Studio Common Project System (CPS) e offre ulteriori punti di estendibilità specifici di C++ per semplificare l'integrazione di nuovi set di strumenti, architetture di compilazione e piattaforme di destinazione.

Struttura delle destinazioni MSBuild C++

Tutti i file .vcxproj importano questi file:

<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

Questi file definiscono poco da soli. Importano invece altri file in base ai valori delle proprietà seguenti:

  • $(ApplicationType)

    Esempi: Windows Store, Android, Linux

  • $(ApplicationTypeRevision)

    Deve essere una stringa di versione valida, del formato major.minor[.build[.revision]].

    Esempi: 1.0, 10.0.0.0

  • $(Platform)

    Architettura di compilazione, denominata "Piattaforma" per motivi cronologici.

    Esempi: Win32, x86, x64, ARM

  • $(PlatformToolset)

    Esempi: v140, v141, v141_xp, llvm

Questi valori delle proprietà specificano i nomi delle cartelle nella $(VCTargetsPath) cartella radice:

$(VCTargetsPath)\
    Tipo di applicazione\
        $(ApplicationType)\
            $(ApplicationTypeRevision)\
                Piattaforme\
                    $(Platform)\
                        PlatformToolsets\
                            $(PlatformToolset)
    Piattaforme\
        $(Platform)\
            PlatformToolsets\
                $(PlatformToolset)

La $(VCTargetsPath)\cartella Platforms\ viene usata quando $(ApplicationType) è vuota per i progetti desktop di Windows.

Aggiungere un nuovo set di strumenti della piattaforma

Per aggiungere un nuovo set di strumenti, ad esempio "MyToolset" per la piattaforma Win32 esistente, creare una cartella MyToolset in $(VCTargetsPath)\Platforms\Win32\PlatformToolsets\e creare file Toolset.props e Toolset.targets in esso contenuti.

Ogni nome di cartella in PlatformToolsets viene visualizzato nella finestra di dialogo Proprietà progetto come set di strumenti della piattaforma disponibile per la piattaforma specificata, come illustrato di seguito:

Proprietà Platform Toolset nella finestra di dialogo Pagine delle proprietà del progetto

Creare cartelle MyToolset simili e file Toolset.props e Toolset.targets in ogni cartella della piattaforma esistente supportata da questo set di strumenti.

Aggiungere una nuova piattaforma

Per aggiungere una nuova piattaforma, ad esempio "MyPlatform", creare una cartella MyPlatform in$(VCTargetsPath) \Platforms\e creare file Platform.default.props, Platform.props e Platform.targets in esso contenuti. Creare anche una $(VCTargetsPath)cartella \Platforms\MyPlatform\PlatformToolsets\ e creare almeno un set di strumenti.

Tutti i nomi di cartella nella cartella Piattaforme per ognuno $(ApplicationType) e $(ApplicationTypeRevision) vengono visualizzati nell'IDE come opzioni di piattaforma disponibili per un progetto.

Nuova piattaforma scelta nella finestra di dialogo Nuova piattaforma progetto

Aggiungere un nuovo tipo di applicazione

Per aggiungere un nuovo tipo di applicazione, creare una cartella MyApplicationType in$(VCTargetsPath) \Application Type\ e crearvi un file Defaults.props. Per un tipo di applicazione è necessaria almeno una revisione, quindi creare anche una $(VCTargetsPath)cartella \Application Type\MyApplicationType\1.0 e creare un file Defaults.props . È anche consigliabile creare una $(VCTargetsPath)cartella \ApplicationType\MyApplicationType\1.0\Platforms e crearvi almeno una piattaforma.

$(ApplicationType) le proprietà e $(ApplicationTypeRevision) non sono visibili nell'interfaccia utente. Vengono definiti nei modelli di progetto e non possono essere modificati dopo la creazione del progetto.

Albero di importazione .vcxproj

Un albero semplificato delle importazioni per i file di proprietà e destinazioni di Microsoft C++ è simile al seguente:

$(VCTargetsPath)\Microsoft.Cpp.Default.props
    $(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props
    $(VCTargetsPath)\ImportBefore\Default\*.trovarobe
    $(VCTargetsPath)\Tipo di\\$(ApplicationType)applicazione Default.props
    $(VCTargetsPath)\Tipo di$(ApplicationTypeRevision)\$(ApplicationType)\\applicazione Default.props
    $(VCTargetsPath)\Platform.default.props\\$(Platform)del tipo di applicazione\$(ApplicationType)\$(ApplicationTypeRevision)\
    $(VCTargetsPath)\ImportAfter\Default\*.trovarobe

I progetti desktop di Windows non definiscono $(ApplicationType), quindi importano solo

$(VCTargetsPath)\Microsoft.Cpp.Default.props
    $(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props
    $(VCTargetsPath)\ImportBefore\Default\*.trovarobe
    $(VCTargetsPath)\Platform.default.props\$(Platform)\
    $(VCTargetsPath)\ImportAfter\Default\*.trovarobe

Verrà usata la $(_PlatformFolder) proprietà per contenere i percorsi delle cartelle della $(Platform) piattaforma. Questa proprietà è

$(VCTargetsPath)\Piattaforme\$(Platform)

per le app desktop di Windows e

$(VCTargetsPath)\Piattaforme del tipo di$(ApplicationTypeRevision)\$(ApplicationType)\\applicazione\$(Platform)

per tutto il resto.

I file props vengono importati in questo ordine:

$(VCTargetsPath)\Microsoft.Cpp.props
    $(_PlatformFolder)\Platform.props
        $(VCTargetsPath)\Microsoft.Cpp.Platform.props
            $(_PlatformFolder)\ImportBefore\*.trovarobe
            $(_PlatformFolder)\PlatformToolsets\\$(PlatformToolset)Toolset.props
            $(_PlatformFolder)\ImportAfter\*.trovarobe

I file di destinazione vengono importati in questo ordine:

$(VCTargetsPath)\Microsoft.Cpp.targets
    $(VCTargetsPath)\Microsoft.Cpp.Current.targets
        $(_PlatformFolder)\Platform.targets
            $(VCTargetsPath)\Microsoft.Cpp.Platform.targets
                $(_PlatformFolder)\ImportBefore\*.Obiettivi
                $(_PlatformFolder)\PlatformToolsets\\$(PlatformToolset)Toolset.target
                $(_PlatformFolder)\ImportAfter\*.Obiettivi

Se è necessario definire alcune proprietà predefinite per il set di strumenti, è possibile aggiungere file alle cartelle ImportBefore e ImportAfter appropriate.

Creare file Toolset.props e Toolset.targets

I file Toolset.props e Toolset.targets hanno il controllo completo su cosa accade durante una compilazione quando viene usato questo set di strumenti. Possono anche controllare i debugger disponibili, alcune delle interfacce utente dell'IDE, ad esempio il contenuto nella finestra di dialogo Pagine delle proprietà e altri aspetti del comportamento del progetto.

Anche se un set di strumenti può eseguire l'override dell'intero processo di compilazione, in genere si vuole solo modificare o aggiungere alcuni passaggi di compilazione o usare strumenti di compilazione diversi, come parte di un processo di compilazione esistente. Per raggiungere questo obiettivo, è possibile importare numerosi file di oggetti visivi e destinazioni comuni che il set di strumenti può importare. A seconda di ciò che si vuole fare il set di strumenti, questi file possono essere utili da usare come importazioni o come esempi:

  • $(VCTargetsPath)\Microsoft.CppCommon.targets

    Questo file definisce le parti principali del processo di compilazione nativo e importa anche:

    • $(VCTargetsPath)\Microsoft.CppBuild.targets

    • $(VCTargetsPath)\Microsoft.BuildSteps.targets

    • $(MSBuildToolsPath)\Microsoft.Common.Targets

  • $(VCTargetsPath)\Microsoft.Cpp.Common.props

    Imposta le impostazioni predefinite per i set di strumenti che usano i compilatori Microsoft e Windows di destinazione.

  • $(VCTargetsPath)\Microsoft.Cpp.WindowsSDK.props

    Questo file determina il percorso di Windows SDK e definisce alcune proprietà importanti per le app destinate a Windows.

Integrare destinazioni specifiche del set di strumenti con il processo di compilazione C++ predefinito

Il processo di compilazione C++ predefinito è definito in Microsoft.CppCommon.targets. Le destinazioni non chiamano strumenti di compilazione specifici; specificano i passaggi di compilazione principali, l'ordine e le dipendenze.

La compilazione C++ include tre passaggi principali, rappresentati dalle destinazioni seguenti:

  • BuildGenerateSources

  • BuildCompile

  • BuildLink

Poiché ogni passaggio di compilazione può essere eseguito in modo indipendente, le destinazioni in esecuzione in un unico passaggio non possono basarsi sui gruppi di elementi e sulle proprietà definite nelle destinazioni eseguite come parte di un passaggio diverso. Questa divisione consente alcune ottimizzazioni delle prestazioni di compilazione. Anche se non viene usato per impostazione predefinita, è comunque consigliabile rispettare questa separazione.

Le destinazioni eseguite all'interno di ogni passaggio sono controllate da queste proprietà:

  • $(BuildGenerateSourcesTargets)

  • $(BuildCompileTargets)

  • $(BeforeBuildLinkTargets)

Ogni passaggio include anche le proprietà Before e After.

<Target
  Name="_BuildGenerateSourcesAction"
  DependsOnTargets="$(CommonBuildOnlyTargets);$(BeforeBuildGenerateSourcesTargets);$(BuildGenerateSourcesTargets);$(AfterBuildGenerateSourcesTargets)" />

<Target
  Name="\_BuildCompileAction"
  DependsOnTargets="$(CommonBuildOnlyTargets);$(BeforeBuildCompileTargets);$(BuildCompileTargets);$(AfterBuildCompileTargets)" />

<Target
  Name="\_BuildLinkAction"
  DependsOnTargets="$(CommonBuildOnlyTargets);$(BeforeBuildLinkTargets);$(BuildLinkTargets);$(AfterBuildLinkTargets)" />

Per esempi delle destinazioni incluse in ogni passaggio, vedere il file Microsoft.CppBuild.targets :

<BuildCompileTargets Condition="'$(ConfigurationType)'\!='Utility'">
  $(BuildCompileTargets);
  _ClCompile;
  _ResGen;
  _ResourceCompile;
  $(BuildLibTargets);
</BuildCompileTargets>

Se si esaminano le destinazioni, ad esempio _ClCompile, si noterà che non eseguono alcuna operazione direttamente da soli, ma dipendono invece da altre destinazioni, tra cui ClCompile:

<Target Name="_ClCompile"
  DependsOnTargets="$(BeforeClCompileTargets);$(ComputeCompileInputsTargets);MakeDirsForCl;ClCompile;$(AfterClCompileTargets)" >
</Target>

ClCompile e altre destinazioni specifiche dello strumento di compilazione sono definite come destinazioni vuote in Microsoft.CppBuild.targets:

<Target Name="ClCompile"/>

Poiché la ClCompile destinazione è vuota, a meno che non venga sottoposta a override da un set di strumenti, non viene eseguita alcuna azione di compilazione reale. Le destinazioni del set di strumenti possono eseguire l'override della ClCompile destinazione, ovvero possono contenere un'altra ClCompile definizione dopo l'importazione di Microsoft.CppBuild.targets:

<Target Name="ClCompile"
  Condition="'@(ClCompile)' != ''"
  DependsOnTargets="SelectClCompile">
  <!-- call some MSBuild tasks -->
</Target>

Nonostante il nome, creato prima che Visual Studio implementi il supporto multipiattaforma, la ClCompile destinazione non deve chiamare CL.exe. Può anche chiamare Clang, gcc o altri compilatori usando le attività MSBuild appropriate.

La ClCompile destinazione non deve avere dipendenze tranne la SelectClCompile destinazione, necessaria per il corretto funzionamento del comando di compilazione del singolo file nell'IDE.

Attività di MSBuild da usare nelle destinazioni del set di strumenti

Per richiamare uno strumento di compilazione effettivo, la destinazione deve chiamare un'attività MSBuild. È disponibile un'attività Exec di base che consente di specificare una riga di comando da eseguire. Tuttavia, gli strumenti di compilazione in genere hanno molte opzioni, input e output per tenere traccia delle compilazioni incrementali, quindi è più opportuno avere attività speciali per loro. Ad esempio, l'attività CL converte le proprietà di MSBuild in opzioni CL.exe, le scrive in un file di risposta e chiama CL.exe. Tiene inoltre traccia di tutti i file di input e output per le compilazioni incrementali successive. Per altre informazioni, vedere Compilazioni incrementali e controlli aggiornati.

Il Microsoft.Cpp.Common.Tasks.dll implementa queste attività:

  • BSCMake

  • CL

  • ClangCompile (commutatori clang-gcc)

  • LIB

  • LINK

  • MIDL

  • Mt

  • RC

  • XDCMake

  • CustomBuild (ad esempio Exec, ma con il rilevamento di input e output)

  • SetEnv

  • GetOutOfDateItems

Se si dispone di uno strumento che esegue la stessa azione di uno strumento esistente e che dispone di opzioni della riga di comando simili (come clang-cl e CL), è possibile usare la stessa attività per entrambi.

Se è necessario creare una nuova attività per uno strumento di compilazione, è possibile scegliere tra le opzioni seguenti:

  1. Se si usa questa attività raramente o se alcuni secondi non sono importanti per la compilazione, è possibile usare le attività "inline" di MSBuild:

    • Attività Xaml (regola di compilazione personalizzata)

      Per un esempio di dichiarazione di attività Xaml, vedi BuildCustomizations masm.xml e per il relativo utilizzo, vedi $(VCTargetsPath)\\$(VCTargetsPath)BuildCustomizations\masm.targets.\

    • Attività Codice

  2. Se si desidera migliorare le prestazioni delle attività o se sono necessarie funzionalità più complesse, usare il normale processo di scrittura delle attività DI MSBuild.

    Se non tutti gli input e gli output dello strumento vengono elencati nella riga di comando dello strumento, come nei CLcasi , MIDLe RC e se si desidera il rilevamento automatico dei file di input e output e la creazione di file con estensione tlog, derivare l'attività dalla Microsoft.Build.CPPTasks.TrackedVCToolTask classe . Attualmente, mentre è disponibile documentazione per la classe ToolTask di base, non sono disponibili esempi o documentazione per i dettagli della TrackedVCToolTask classe. Se questo sarebbe di particolare interesse, aggiungere la voce a una richiesta nella community degli sviluppatori.

Compilazioni incrementali e controlli aggiornati

Le destinazioni di compilazione incrementali di MSBuild predefinite usano Inputs attributi e Outputs . Se vengono specificati, MSBuild chiama la destinazione solo se uno degli input ha un timestamp più recente rispetto a tutti gli output. Poiché i file di origine spesso includono o importano altri file e gli strumenti di compilazione producono output diversi a seconda delle opzioni dello strumento, è difficile specificare tutti gli input e gli output possibili nelle destinazioni MSBuild.

Per gestire questo problema, la compilazione C++ usa una tecnica diversa per supportare compilazioni incrementali. La maggior parte delle destinazioni non specifica input e output e, di conseguenza, viene sempre eseguita durante la compilazione. Le attività chiamate dalle destinazioni scrivono informazioni su tutti gli input e gli output in file tlog con estensione tlog. I file con estensione tlog vengono usati dalle compilazioni successive per verificare cosa è stato modificato e deve essere ricompilato e cosa è aggiornato. I file con estensione tlog sono anche l'unica origine per l'archiviazione predefinita di compilazione aggiornata nell'IDE.

Per determinare tutti gli input e gli output, le attività dello strumento nativo usano tracker.exe e la classe FileTracker fornita da MSBuild.

Microsoft.Build.CPPTasks.Common.dll definisce la TrackedVCToolTask classe base astratta pubblica. La maggior parte delle attività dello strumento nativo è derivata da questa classe.

A partire da Visual Studio 2017 update 15.8, è possibile usare l'attività GetOutOfDateItems implementata in Microsoft.Cpp.Common.Tasks.dll per produrre file con estensione tlog per destinazioni personalizzate con input e output noti. In alternativa, è possibile crearli usando l'attività WriteLinesToFile . Vedere la _WriteMasmTlogs destinazione in $(VCTargetsPath)\BuildCustomizations\masm.targets come esempio.

File con estensione tlog

Esistono tre tipi di file con estensione tlog: lettura, scrittura e riga di comando. I file con estensione tlog di lettura e scrittura vengono usati dalle compilazioni incrementali e dal controllo aggiornato nell'IDE. I file con estensione tlog della riga di comando vengono usati solo nelle compilazioni incrementali.

MSBuild fornisce queste classi helper per leggere e scrivere file con estensione tlog:

La classe FlatTrackingData può essere usata per accedere ai file con estensione tlog di lettura e scrittura e identificare gli input più recenti rispetto agli output oppure se manca un output. Viene usato nel controllo aggiornato.

I file con estensione tlog della riga di comando contengono informazioni sulle righe di comando usate nella compilazione. Vengono usati solo per le compilazioni incrementali, non per i controlli aggiornati, quindi il formato interno è determinato dall'attività MSBuild che li produce.

Leggere il formato tlog

Leggere i file con estensione tlog (*.read.*.tlog) contenenti informazioni sui file di origine e sulle relative dipendenze.

Un cursore (^) all'inizio di una riga indica una o più origini. Le origini che condividono le stesse dipendenze sono separate da una barra verticale (|).

I file di dipendenza vengono elencati dopo le origini, ognuna nella propria riga. Tutti i nomi di file sono percorsi completi.

Si supponga, ad esempio, che le origini del progetto siano disponibili in F:\test\ConsoleApplication1\ConsoleApplication1. Se il file di origine, Class1.cpp, include questi elementi,

#include "stdafx.h" //precompiled header
#include "Class1.h"

il file CL.read.1.tlog contiene quindi il file di origine seguito dalle due dipendenze seguenti:

^F:\TEST\CONSOLEAPPLICATION1\CONSOLEAPPLICATION1\CLASS1.CPP
F:\TEST\CONSOLEAPPLICATION1\CONSOLEAPPLICATION1\DEBUG\CONSOLEAPPLICATION1.PCH
F:\TEST\CONSOLEAPPLICATION1\CONSOLEAPPLICATION1\CLASS1.H

Non è necessario scrivere nomi di file in lettere maiuscole, ma è una comodità per alcuni strumenti.

Scrivere il formato tlog

Scrivere file con estensione tlog (*.write.*.tlog) che connettono origini e output.

Un cursore (^) all'inizio di una riga indica una o più origini. Più origini sono separate da una barra verticale (|).

I file di output compilati dalle origini devono essere elencati dopo le origini, ognuna in base alla propria riga. Tutti i nomi di file devono essere percorsi completi.

Ad esempio, per un semplice progetto ConsoleApplication con un file di origine aggiuntivo Class1.cpp, il file link.write.1.tlog può contenere:

^F:\TEST\CONSOLEAPPLICATION1\CONSOLEAPPLICATION1\DEBUG\CLASS1.OBJ|F:\TEST\CONSOLEAPPLICATION1\CONSOLEAPPLICATION1\DEBUG\CONSOLEAPPLICATION1.OBJ|F:\TEST\CONSOLEAPPLICATION1\CONSOLEAPPLICATION1\DEBUG\STDAFX.OBJ
F:\TEST\CONSOLEAPPLICATION1\DEBUG\CONSOLEAPPLICATION1.ILK
F:\TEST\CONSOLEAPPLICATION1\DEBUG\CONSOLEAPPLICATION1.EXE
F:\TEST\CONSOLEAPPLICATION1\DEBUG\CONSOLEAPPLICATION1.PDB

Compilazione in fase di progettazione

Nell'IDE .vcxproj i progetti usano un set di destinazioni MSBuild per ottenere informazioni aggiuntive dal progetto e rigenerare i file di output. Alcune di queste destinazioni vengono usate solo nelle build in fase di progettazione, ma molte di esse vengono usate sia nelle compilazioni regolari che nelle build in fase di progettazione.

Per informazioni generali sulle compilazioni in fase di progettazione, vedere la documentazione cps per le compilazioni in fase di progettazione. Questa documentazione è applicabile solo parzialmente ai progetti Visual C++.

Le CompileDesignTime destinazioni e Compile indicate nella documentazione relativa alle compilazioni in fase di progettazione non vengono mai eseguite per i progetti .vcxproj. I progetti visual C++ .vcxproj usano destinazioni in fase di progettazione diverse per ottenere informazioni su IntelliSense.

Destinazioni in fase di progettazione per informazioni su IntelliSense

Le destinazioni in fase di progettazione usate nei progetti .vcxproj sono definite in $(VCTargetsPath)\Microsoft.Cpp.DesignTime.targets.

La GetClCommandLines destinazione raccoglie le opzioni del compilatore per IntelliSense:

<Target
  Name="GetClCommandLines"
  Returns="@(ClCommandLines)"
  DependsOnTargets="$(DesignTimeBuildInitTargets);$(ComputeCompileInputsTargets)">
  • DesignTimeBuildInitTargets : destinazioni solo in fase di progettazione, necessarie per l'inizializzazione della compilazione in fase di progettazione. Tra le altre cose, queste destinazioni disabilitano alcune delle normali funzionalità di compilazione per migliorare le prestazioni.

  • ComputeCompileInputsTargets : set di destinazioni che modifica le opzioni e gli elementi del compilatore. Queste destinazioni vengono eseguite sia in fase di progettazione che in compilazioni regolari.

La destinazione chiama l'attività CLCommandLine per creare la riga di comando da usare per IntelliSense. Anche in questo caso, nonostante il nome, può gestire non solo le opzioni CL, ma anche le opzioni Clang e gcc. Il tipo di opzioni del compilatore è controllato dalla ClangMode proprietà .

Attualmente, la riga di comando prodotta dall'attività CLCommandLine usa sempre commutatori CL (anche in modalità Clang) perché sono più facili per il motore IntelliSense da analizzare.

Se si aggiunge una destinazione eseguita prima della compilazione, sia normale che in fase di progettazione, assicurarsi che non interrompa le compilazioni in fase di progettazione o influisca sulle prestazioni. Il modo più semplice per testare la destinazione consiste nell'aprire un prompt dei comandi per gli sviluppatori ed eseguire questo comando:

msbuild /p:SolutionDir=*solution-directory-with-trailing-backslash*;Configuration=Debug;Platform=Win32;BuildingInsideVisualStudio=true;DesignTimebuild=true /t:\_PerfIntellisenseInfo /v:d /fl /fileloggerparameters:PerformanceSummary \*.vcxproj

Questo comando genera un log di compilazione dettagliato, msbuild.log, con un riepilogo delle prestazioni per le destinazioni e le attività alla fine.

Assicurarsi di usare Condition ="'$(DesignTimeBuild)' != 'true'" in tutte le operazioni che hanno senso solo per le compilazioni regolari e non per le compilazioni in fase di progettazione.

Destinazioni in fase di progettazione che generano origini

Questa funzionalità è disabilitata per impostazione predefinita per i progetti nativi desktop e non è attualmente supportata nei progetti memorizzati nella cache.

Se GeneratorTarget i metadati sono definiti per un elemento di progetto, la destinazione viene eseguita automaticamente sia quando il progetto viene caricato che quando viene modificato il file di origine.

Ad esempio, per generare automaticamente file .cpp o h da file con estensione xaml, i $(VSInstallDir)\file MSBuild\Microsoft\WindowsXaml\v16.0\*\Microsoft.Windows.UI.Xaml.CPP.Targets definiscono queste entità:

<ItemDefinitionGroup>
  <Page>
    <GeneratorTarget>DesignTimeMarkupCompilation</GeneratorTarget>
  </Page>
  <ApplicationDefinition>
    <GeneratorTarget>DesignTimeMarkupCompilation</GeneratorTarget>
  </ApplicationDefinition>
</ItemDefinitionGroup>
<Target Name="DesignTimeMarkupCompilation">
  <!-- BuildingProject is used in Managed builds (always true in Native) -->
  <!-- DesignTimeBuild is used in Native builds (always false in Managed) -->
  <CallTarget Condition="'$(BuildingProject)' != 'true' Or $(DesignTimeBuild) == 'true'" Targets="DesignTimeMarkupCompilationCT" />
</Target>

Per usare Task.HostObject per ottenere il contenuto non salvato dei file di origine, le destinazioni e le attività devono essere registrate come MsbuildHostObjects per i progetti specificati in un pkgdef:

\[$RootKey$\\Projects\\{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\\MSBuildHostObjects\]
\[$RootKey$\\Projects\\{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\\MSBuildHostObjects\\DesignTimeMarkupCompilationCT;CompileXaml\]
@="{83046B3F-8984-444B-A5D2-8029DEE2DB70}"

Estendibilità del progetto Visual C++ nell'IDE di Visual Studio

Il sistema di progetto Visual C++ si basa sul sistema di progetto VS e usa i relativi punti di estendibilità. Tuttavia, l'implementazione della gerarchia del progetto è specifica di Visual C++ e non basata su CPS, quindi l'estendibilità della gerarchia è limitata agli elementi del progetto.

Pagina delle proprietà del progetto

Per informazioni generali sulla progettazione, vedere Framework multitargeting per progetti VC++.

In termini semplici, le pagine delle proprietà visualizzate nella finestra di dialogo Proprietà progetto per un progetto C++ sono definite dai file delle regole . Un file di regole specifica un set di proprietà da visualizzare in una pagina delle proprietà e come e dove devono essere salvati nel file di progetto. I file delle regole sono .xml file che usano il formato Xaml. I tipi usati per serializzarli sono descritti in Microsoft.Build.Framework.XamlTypes. Per altre informazioni sull'uso dei file di regole nei progetti, vedere File di regole XML della pagina delle proprietà.

I file delle regole devono essere aggiunti al gruppo di PropertyPageSchema elementi:

<ItemGroup>
  <PropertyPageSchema Include="$(VCTargetsPath)$(LangID)\general.xml;"/>
  <PropertyPageSchema Include="$(VCTargetsPath)$(LangID)\general_file.xml">
    <Context>File</Context>
  </PropertyPageSchema>
</ItemGroup>

Context la visibilità delle regole dei metadati, controllata anche dal tipo di regola, e può avere uno di questi valori:

Project | File | PropertySheet

CPS supporta altri valori per il tipo di contesto, ma non vengono usati nei progetti Visual C++.

Se la regola deve essere visibile in più contesti, usare punti e virgola (;) per separare i valori di contesto, come illustrato di seguito:

<PropertyPageSchema Include="$(MyFolder)\MyRule.xml">
  <Context>Project;PropertySheet</Context>
</PropertyPageSchema>

Formato delle regole e tipi principali

Il formato della regola è semplice, quindi questa sezione descrive solo gli attributi che influiscono sull'aspetto della regola nell'interfaccia utente.

<Rule
  Name="ConfigurationGeneral"
  DisplayName="General"
  PageTemplate="generic"
  Description="General"
  xmlns="http://schemas.microsoft.com/build/2009/properties">

L'attributo PageTemplate definisce la modalità di visualizzazione della regola nella finestra di dialogo Pagine delle proprietà. L'attributo può avere uno dei valori seguenti:

Attributo Descrizione
generic Tutte le proprietà vengono visualizzate in una pagina in Intestazioni categoria
La regola può essere visibile per Project i contesti e PropertySheet , ma non Fileper .

Esempio: $(VCTargetsPath)\1033\general.xml
tool Le categorie vengono visualizzate come pagine secondarie.
La regola può essere visibile in tutti i contesti: Projecte PropertySheet File.
La regola è visibile in Proprietà progetto solo se il progetto contiene elementi con l'oggetto ItemType definito in Rule.DataSource, a meno che il nome della regola non sia incluso nel ProjectTools gruppo di elementi.

Esempio: $(VCTargetsPath)\1033\clang.xml
debugger La pagina viene visualizzata come parte della pagina Debug.
Le categorie vengono attualmente ignorate.
Il nome della regola deve corrispondere all'attributo dell'oggetto MEF dell'utilità di avvio di ExportDebugger debug.

Esempio: $(VCTargetsPath)\1033\debugger_local_windows.xml
custom Modello personalizzato. Il nome del modello deve corrispondere all'attributo ExportPropertyPageUIFactoryProvider dell'oggetto PropertyPageUIFactoryProvider MEF. Vedere Microsoft.VisualStudio.ProjectSystem.Designers.Properties.IPropertyPageUIFactoryProvider.

Esempio: $(VCTargetsPath)\1033\userMacros.xml

Se la regola usa uno dei modelli basati su Griglia di proprietà, può usare questi punti di estendibilità per le relative proprietà:

Estendere una regola

Se si vuole usare una regola esistente, ma è necessario aggiungere o rimuovere (ovvero nascondere) solo alcune proprietà, è possibile creare una regola di estensione.

Eseguire l'override di una regola

È possibile che il set di strumenti usi la maggior parte delle regole predefinite del progetto, ma per sostituire solo uno o pochi di essi. Si supponga, ad esempio, di voler modificare solo la regola C/C++ in modo da visualizzare opzioni del compilatore diverse. È possibile specificare una nuova regola con lo stesso nome e nome visualizzato della regola esistente e includerla nel PropertyPageSchema gruppo di elementi dopo l'importazione di destinazioni cpp predefinite. Nel progetto viene usata una sola regola con un nome specificato e l'ultima inclusa nel PropertyPageSchema gruppo di elementi prevale.

Articoli progetto

Il file ProjectItemsSchema.xml definisce i ContentType valori e ItemType per Items trattati come Elementi di progetto e definisce FileExtension gli elementi per determinare il gruppo item a cui viene aggiunto un nuovo file.

Il file ProjectItemsSchema predefinito è disponibile in $(VCTargetsPath)\1033\ProjectItemsSchema.xml. Per estenderlo, è necessario creare un file di schema con un nuovo nome, ad esempio MyProjectItemsSchema.xml:

<ProjectSchemaDefinitions xmlns="http://schemas.microsoft.com/build/2009/properties">

  <ItemType Name="MyItemType" DisplayName="C/C++ compiler"/>

  <ContentType
    Name="MyItems"
    DisplayName="My items"
    ItemType=" MyItemType ">
  </ContentType>

  <FileExtension Name=".abc" ContentType=" MyItems"/>

</ProjectSchemaDefinitions>

Quindi, nel file di destinazioni aggiungere:

<ItemGroup>
  <PropertyPageSchema Include="MyProjectItemsSchema.xml"/>
</ItemGroup>

Esempio: $(VCTargetsPath)\BuildCustomizations\masm.xml

Debugger

Il servizio Debug in Visual Studio supporta l'estendibilità per il motore di debug. Per altre informazioni, vedere questi esempi:

Per specificare i motori di debug e altre proprietà per la sessione di debug, è necessario implementare un componente MEF di avvio del debug e aggiungere una debugger regola. Per un esempio, vedere il $(VCTargetsPath)file \1033\debugger_local_windows.xml.

Distribuzione

.vcxproj progetti usano l'estendibilità del sistema di progetto di Visual Studio per i provider di distribuzione.

Verifica aggiornata

Per impostazione predefinita, il controllo di aggiornamento della compilazione richiede la lettura di file con estensione tlog e la scrittura di file tlog nella cartella durante la $(TlogLocation) compilazione per tutti gli input e gli output di compilazione.

Per usare un controllo personalizzato aggiornato:

  1. Disabilitare il controllo predefinito aggiornato aggiungendo la NoVCDefaultBuildUpToDateCheckProvider funzionalità nel file Toolset.targets :

    <ItemGroup>
      <ProjectCapability Include="NoVCDefaultBuildUpToDateCheckProvider" />
    </ItemGroup>
    
  2. Implementare i propri IBuildUpToDateCheckProvider.

Aggiornamento del progetto

Aggiornamento predefinito .vcxproj progetto

L'aggiornamento del progetto predefinito .vcxproj modifica la versione del PlatformToolsetset di strumenti , ApplicationTypeRevision, MSBuild e .NET Framework. Le ultime due vengono sempre modificate nelle impostazioni predefinite della versione di Visual Studio, ma PlatformToolset possono ApplicationTypeRevision essere controllate da proprietà MSBuild speciali.

L'aggiornamento usa questi criteri per decidere se un progetto può essere aggiornato o meno:

  1. Per i progetti che definiscono ApplicationType e ApplicationTypeRevision, è presente una cartella con un numero di revisione superiore a quello corrente.

  2. La proprietà _UpgradePlatformToolsetFor_<safe_toolset_name> viene definita per il set di strumenti corrente e il relativo valore non è uguale al set di strumenti corrente.

    In questi nomi di proprietà safe_toolset_name <>rappresenta il nome del set di strumenti con tutti i caratteri non alfanumerici sostituiti da un carattere di sottolineatura (_).

Quando un progetto può essere aggiornato, partecipa a Retargeting della soluzione. Per altre informazioni, vedere IVsTrackProjectRetargeting2.

Se si desidera adornare i nomi di progetto in Esplora soluzioni quando i progetti usano un set di strumenti specifico, definire una _PlatformToolsetShortNameFor_<safe_toolset_name> proprietà.

Per esempi di definizioni di _UpgradePlatformToolsetFor_<safe_toolset_name> proprietà e _PlatformToolsetShortNameFor_<safe_toolset_name> , vedere il file Microsoft.Cpp.Default.props . Per esempi di utilizzo, vedere il $(VCTargetPath)\file Microsoft.Cpp.Platform.targets .

Aggiornamento del progetto personalizzato

Per usare un oggetto upgrader di progetto personalizzato, implementare un componente MEF, come illustrato di seguito:

/// </summary>
[Export("MyProjectUpgrader", typeof(IProjectRetargetHandler))]
[Export(typeof(IProjectRetargetHandler))]
[ExportMetadata("Name", "MyProjectUpgrader")]
[OrderPrecedence(20)]
[PartMetadata(ProjectCapabilities.Requires, ProjectCapabilities.VisualC)]

internal class MyProjectUpgrader: IProjectRetargetHandler
{
    // ...
}

Il codice può importare e chiamare l'oggetto upgrader predefinito .vcxproj:

// ...
[Import("VCDefaultProjectUpgrader")]
// ...
    IProjectRetargetHandler Lazy<IProjectRetargetHandler>
    VCDefaultProjectUpgrader { get; set; }
// ...

IProjectRetargetHandler è definito in Microsoft.VisualStudio.ProjectSystem.VS.dll ed è simile a IVsRetargetProjectAsync.

Definire la VCProjectUpgraderObjectName proprietà per indicare al sistema di progetto di usare l'oggetto upgrader personalizzato:

<PropertyGroup>
  <VCProjectUpgraderObjectName>MyProjectUpgrader</VCProjectUpgraderObjectName>
</PropertyGroup>

Disabilitare l'aggiornamento del progetto

Per disabilitare gli aggiornamenti del progetto, usare un NoUpgrade valore:

<PropertyGroup>
  <VCProjectUpgraderObjectName>NoUpgrade</VCProjectUpgraderObjectName>
</PropertyGroup>

Cache ed estendibilità del progetto

Per migliorare le prestazioni quando si lavora con soluzioni C++ di grandi dimensioni in Visual Studio 2017, è stata introdotta la cache del progetto. Viene implementato come database SQLite popolato con dati di progetto e quindi usato per caricare i progetti senza caricare progetti MSBuild o CPS in memoria.

Poiché non sono presenti oggetti CPS per i progetti .vcxproj caricati dalla cache, i componenti MEF dell'estensione che importano UnconfiguredProject o ConfiguredProject non possono essere creati. Per supportare l'estendibilità, la cache del progetto non viene usata quando Visual Studio rileva se un progetto usa (o è probabile che usi) estensioni MEF.

Questi tipi di progetto sono sempre completamente caricati e dispongono di oggetti CPS in memoria, quindi tutte le estensioni MEF vengono create per loro:

  • Progetti di avvio

  • I progetti che dispongono di un aggiornamento del progetto personalizzato, ovvero definiscono una VCProjectUpgraderObjectName proprietà

  • I progetti che non hanno come destinazione Windows desktop, ovvero definiscono una ApplicationType proprietà

  • Progetti di elementi condivisi (con estensione vcxitems) e tutti i progetti che vi fanno riferimento tramite importazione di progetti vcxitems.

Se nessuna di queste condizioni viene rilevata, viene creata una cache del progetto. La cache include tutti i dati del progetto MSBuild necessari per rispondere get alle query sulle VCProjectEngine interfacce. Ciò significa che tutte le modifiche a livello di file msBuild e di destinazione eseguite da un'estensione dovrebbero funzionare solo nei progetti caricati dalla cache.

Spedizione dell'estensione

Per informazioni su come creare file VSIX, vedere Shipping Visual Studio Extensions .For information on how to create VSIX files, see Shipping Visual Studio Extensions. Per informazioni su come aggiungere file a percorsi di installazione speciali, ad esempio per aggiungere file in $(VCTargetsPath), vedere Installazione all'esterno della cartella delle estensioni.

Risorse aggiuntive

Microsoft Build System (MSBuild) fornisce il motore di compilazione e il formato estensibile basato su XML per i file di progetto. È necessario avere familiarità con i concetti di base di MSBuild e con il funzionamento di MSBuild per Visual C++ per estendere il sistema di progetto Visual C++.

Managed Extensibility Framework (MEF) fornisce le API di estensione usate da CPS e dal sistema di progetto Visual C++. Per una panoramica del modo in cui MEF viene usato da CPS, vedere CPS e MEF nella panoramica di VSProjectSystem di MEF.

È possibile personalizzare il sistema di compilazione esistente per aggiungere passaggi di compilazione o nuovi tipi di file. Per altre informazioni, vedere Panoramica di MSBuild (Visual C++) e Uso delle proprietà del progetto.