.vcxproj
と .props
ファイルの構造
MSBuild は、Visual Studio の既定のプロジェクト システムです。Visual C++ で [ファイル]>[新しいプロジェクト] を選ぶと、MSBuild プロジェクトが作成されて、その設定が拡張子 .vcxproj
の XML プロジェクト ファイルに格納されます。 プロジェクト ファイルでは .props
ファイルと .targets
ファイルをインポートすることもでき、これらのファイルにも設定を格納できます。
IDE でプロジェクトのプロパティを維持する場合は、IDE で .vcxproj
プロジェクトのみを作成および変更し、ファイルを手動で編集しないようにすることをお勧めします。 ほとんどの場合、プロジェクト ファイルを手動で編集する必要はありません。 手動で編集すると、Visual Studio プロパティ ページのプロジェクト設定を変更するために必要なプロジェクト接続が切断され、デバッグや修復が困難なビルド エラーが発生する可能性があります。 プロパティ ページの使用方法の詳細については、「 Set C++ コンパイラとビルド プロパティを Visual Studio で設定するを参照してください。
大規模に、IDE で多数の個々のプロジェクトを管理することは面倒になり、エラーが発生しやすくなります。 一貫性を維持したり、数十から数百のプロジェクトにわたって標準化を実施したりすることは困難です。 このような場合は、プロジェクト ファイルを編集して、カスタマイズされた .props
または .targets
ファイルを多くのプロジェクトの共通プロパティに使用する価値があります。 IDE では不可能なカスタマイズが必要な場合は、これらのファイルを使用することもできます。 Directory.Build.props
ファイルと Directory.Build.targets
ファイルはカスタマイズを挿入する便利な場所で、すべての MSBuild ベースのプロジェクトに自動的にインポートされます。
場合によっては、カスタマイズされた .props
または .targets
ファイルだけでは、プロジェクト管理のニーズに十分でない場合があります。 プロジェクト ファイルまたはプロパティ シート .vcxproj
手動で変更する必要がある場合があります。 手動編集では、MSBuild をよく理解している必要があり、この記事のガイドラインに従う必要があります。 IDE で .vcxproj
ファイルを自動的に読み込んで更新するために、これらのファイルには、MSBuild のその他のプロジェクト ファイルには適用されないいくつかの制限があります。 間違いがあると、IDE がクラッシュしたり、予期しない動作が発生したりする可能性があります。
手動で編集するシナリオのために、この記事では .vcxproj
と関連ファイルの構造に関する基本的な情報を提供します。
重要な考慮事項
.vcxproj
ファイルを手動で編集する場合は、次のことに注意してください。
ファイルの構造は、この記事に記載されている所定のフォームに従う必要があります。
現在、Visual Studio C++ プロジェクト システムでは、プロジェクト項目でワイルドカードとリストを直接的にはサポートしていません。 たとえば、次の形式はサポートしていません。
<ItemGroup> <None Include="*.txt"/> <ClCompile Include="a.cpp;b.cpp"/> </ItemGroup>
プロジェクトでのワイルドカードのサポートと考えられる回避策の詳細については、「
.vcxproj
ファイルとワイルドカード」を参照してください。現在、Visual Studio C++ プロジェクト システムでは、プロジェクト項目パスでのマクロをサポートしていません。 たとえば、次の形式はサポートしていません。
<ItemGroup> <ClCompile Include="$(IntDir)\generated.cpp"/> </ItemGroup>
"サポートされていない" とは、IDE において、すべての操作に対してマクロが機能することが保証されないという意味です。 異なる構成でその値を変えないマクロは機能するはずですが、ある項目が別のフィルターまたはプロジェクトに移動すると保持されないことがあります。 構成ごとに値が変化するマクロを使用すると、問題が発生します。 IDE では、プロジェクト項目のパスがプロジェクト構成ごとに異なるとは想定されていません。
[プロジェクトのプロパティ] ダイアログで編集するときにプロジェクトのプロパティを正しく追加、削除、変更するには、ファイルにプロジェクト構成ごとに別個のグループが含まれている必要があります。 条件は次の形式で指定する必要があります。
Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"
各プロパティは、プロパティ規則ファイル内で指定されている正しいラベルを持つグループにおいて指定されている必要があります。 詳しくは、「プロパティ ページの XML 規則ファイル」をご覧ください。
.vcxproj
ファイルの要素
任意のテキスト エディターまたは XML エディターを使用して、.vcxproj
ファイルの内容を調べることができます。 Visual Studio のソリューション エクスプローラーでプロジェクトを右クリックし、[プロジェクトのアンロード]、[Foo.vcxproj の編集] の順に選ぶと表示されます。
最初に注目する点は、最上位の要素が特定の順序で表示されることです。 次に例を示します。
ほとんどのプロパティ グループおよび項目定義グループは、Microsoft.Cpp.Default.props のインポートの後に出現します。
すべてのターゲットは、ファイルの最後にインポートされます。
複数のプロパティ グループがあり、それぞれが一意のラベルを持ち、特定の順序で出現します。
MSBuild は順次評価モデルに基づいているため、プロジェクト ファイル内の要素の順序が非常に重要です。 インポートされたすべての .props
ファイルと .targets
ファイルを含むプロジェクト ファイルが、複数のプロパティ定義で構成されている場合、最後の定義によって前の定義がオーバーライドされます。 次の例では、コンパイル中に値 "xyz" が設定されますが、これは MSBUild エンジンによる評価中に値 "xyz" が最後に検出されるためです。
<MyProperty>abc</MyProperty>
<MyProperty>xyz</MyProperty>
次のスニペットに、最小限の .vcxproj
ファイルを示します。 Visual Studio によって生成される .vcxproj
ファイルには、それら MSBuild の最上位の要素が含まれます。 また、そのような最上位の各要素の複数のコピーが含まれている場合もありますが、この順序で表示されます。 Label
属性は任意のタグであり、Visual Studio によって編集のための目印としてのみ使用されます。それ以外の機能はありません。
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
<ItemGroup Label="ProjectConfigurations" />
<PropertyGroup Label="Globals" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.default.props" />
<PropertyGroup Label="Configuration" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings" />
<ImportGroup Label="PropertySheets" />
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<ItemDefinitionGroup />
<ItemGroup />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets" />
</Project>
次のセクションでは、これらの各要素の目的と、その順序の理由について説明します。
Project 要素
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns='http://schemas.microsoft.com/developer/msbuild/2003' >
Project
はルート ノードです。 使用される MSBuild のバージョンを指定し、このファイルが MSBuild.exe に渡されたときに実行する既定のターゲットも指定します。
ItemGroup の ProjectConfigurations 要素
<ItemGroup Label="ProjectConfigurations" />
ProjectConfigurations
には、プロジェクトの構成の説明が含まれます。 たとえば、Debug|Win32、Release|Win32、Debug|ARM などです。 プロジェクトの多くの設定は、特定の構成に固有です。 たとえば、リリース ビルドでは最適化プロパティを設定しても、デバッグ ビルドでは設定しないことがあります。
ProjectConfigurations
項目グループは、ビルド時には使用されません。 Visual Studio IDE でプロジェクトを読み込むために必要です。 この項目グループを .props
ファイルに移動して、.vcxproj
ファイルにインポートすることができます。 ただし、その際に、構成の追加または削除が必要になった場合は、.props
ファイルを手動で編集する必要があります。IDE を使用することはできません。
ProjectConfiguration 要素
次のスニペットでは、プロジェクトの構成を示します。 この例では、"Debug|x64" が構成の名前です。 プロジェクトの構成の名前は、$(Configuration)|$(Platform)
という形式になっている必要があります。 ProjectConfiguration
ノードには、Configuration
と Platform
という 2 つのプロパティがある場合があります。 構成がアクティブになると、ここで指定した値がこれらのプロパティに自動的に設定されます。
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
IDE では、すべての ProjectConfiguration
項目で使用されている Configuration
と Platform
の値の任意の組み合わせに対して、プロジェクトの構成が見つかるものと想定しています。 多くの場合、これはこの要件を満たすためにプロジェクトに意味のないプロジェクト構成が存在する可能性があることを意味します。 たとえば、プロジェクトに次のような構成があるものとします。
Debug|Win32
Retail|Win32
Special 32-bit Optimization|Win32
この場合、"Special 32-bit Optimization" は x64 に対しては意味がありませんが、次のような構成も存在する必要があります。
Debug|x64
Retail|x64
Special 32-bit Optimization|x64
ソリューション構成マネージャーでは、任意の構成に対してビルドと配置のコマンドを無効にできます。
PropertyGroup の Globals 要素
<PropertyGroup Label="Globals" />
Globals
には、ProjectGuid
、RootNamespace
、ApplicationType
または ApplicationTypeRevision
などのプロジェクト レベルの設定が含まれます。 最後の 2 つは、多くの場合、ターゲット OS を定義します。 プロジェクトでターゲットに設定できるのは単一の OS のみです。現在、参照やプロジェクト項目には条件を設定できないためです。 これらのプロパティは、通常、プロジェクト ファイル内の他の場所ではオーバーライドされません。 このグループは構成に依存しないので、普通、プロジェクト ファイル内に存在する Globals
グループは 1 つのみです。
Import の Microsoft.Cpp.default.props 要素
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.default.props" />
Microsoft.Cpp.default.props プロパティ シートは Visual Studio に付属しており、変更できません。 プロジェクトの既定の設定が含まれます。 既定値は、ApplicationType によって異なる場合があります。
PropertyGroup の Configuration 要素
<PropertyGroup Label="Configuration" />
Configuration
プロパティ グループには、添付された構成条件 (Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"
など) があり、構成ごとに 1 つずつの、複数のコピーが提供されます。 このプロパティ グループは、特定の構成に対して設定されるプロパティをホストします。 構成プロパティは PlatformToolset を含み、Microsoft.Cpp.props でのシステム プロパティ シートのインクルードも制御します。 たとえば、プロパティ <CharacterSet>Unicode</CharacterSet>
を定義した場合、システム プロパティ シート microsoft.Cpp.unicodesupport.props がインクルードされます。 Microsoft.Cpp.props を調べると、<Import Condition="'$(CharacterSet)' == 'Unicode'" Project="$(VCTargetsPath)\microsoft.Cpp.unicodesupport.props" />
という行が見つかります。
Import の Microsoft.Cpp.props 要素
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
Microsoft.Cpp.props プロパティ シートでは、多くのツール固有プロパティの既定値が (直接的に、またはインポートを介して) 定義されています。 例として、コンパイラの最適化と警告レベルのプロパティや、MIDL ツールの TypeLibraryName プロパティなどが含まれます。 また、その直前にあるプロパティ グループで定義されている構成プロパティに基づいて、さまざまなシステム プロパティ シートをインポートします。
ImportGroup の ExtensionSettings 要素
<ImportGroup Label="ExtensionSettings" />
ExtensionSettings
グループには、ビルドのカスタマイズの一部であるプロパティ シートのインポートが含まれます。 ビルドのカスタマイズは、最大 3 つのファイル (.targets
ファイル、.props
ファイル、.xml
ファイル) によって定義されます。 このインポート グループには、.props
ファイルのインポートが含まれています。
ImportGroup の PropertySheets 要素
<ImportGroup Label="PropertySheets" />
PropertySheets
グループには、ユーザー プロパティ シートのインポートが含まれます。 これらのインポートは、Visual Studio のプロパティ マネージャー ビューを通じて追加するプロパティ シートです。 これらのインポートは列記されている順序が重要であり、プロパティ マネージャーに反映されます。 通常、プロジェクト ファイルには、この種のインポート グループの複数のインスタンス (プロジェクト構成ごとに 1 つずつ) が含まれます。
PropertyGroup の UserMacros 要素
<PropertyGroup Label="UserMacros" />
UserMacros
には、ユーザーが変数として作成し、ビルド プロセスのカスタマイズに使われるプロパティが含まれます。 たとえば、カスタム出力パスを定義するためのユーザー マクロを $(CustomOutputPath) として定義し、それを使って他の変数を定義できます。 このプロパティ グループは、そのようなプロパティを格納します。 Visual Studio では、Visual C++ が構成用のユーザー マクロをサポートしていないため、このグループはプロジェクト ファイル内に作成されません。 ユーザー マクロは、プロパティ シートでサポートされています。
構成ごとの PropertyGroup 要素
<PropertyGroup />
このプロパティ グループには、すべてのプロジェクト構成の構成ごとに 1 つずつ、複数のインスタンスがあります。 各プロパティ グループには、1 つの構成条件が添付されている必要があります。 いずれかの構成がない場合、[プロジェクトのプロパティ] ダイアログは正しく動作しません。 前に示したプロパティ グループとは異なり、このグループにはラベルがありません。 このグループには、プロジェクトの構成レベルの設定が含まれます。 これらの設定は、指定された項目グループの一部であるすべてのファイルに適用されます。 ビルドのカスタマイズ項目定義のメタデータはここで初期化されます。
この PropertyGroup は <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
の後に続ける必要があり、それより前に Label のない他の PropertyGroup が存在していてはなりません (そうしないと、プロジェクトのプロパティの編集が正しく動作しません)。
構成ごとの ItemDefinitionGroup 要素
<ItemDefinitionGroup />
項目の定義が含まれます。 それらの定義は、ラベルのない構成ごとの PropertyGroup
要素と同じ条件規則に従う必要があります。
ItemGroup 要素
<ItemGroup />
ItemGroup
要素には、プロジェクト内の項目 (ソース ファイルなど) が格納されます。 プロジェクト項目 (つまり、規則の定義によってプロジェクト項目として扱われる項目の種類) に対しては、条件はサポートされていません。
メタデータでは、構成ごとに構成の条件が必要です (すべて同じであっても)。 次に例を示します。
<ItemGroup>
<ClCompile Include="stdafx.cpp">
<TreatWarningAsError Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</TreatWarningAsError>
<TreatWarningAsError Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</TreatWarningAsError>
</ClCompile>
</ItemGroup>
Visual Studio C++ プロジェクト システムでは現在、プロジェクト項目でのワイルドカードをサポートしていません。
<ItemGroup>
<ClCompile Include="*.cpp"> <!--Error-->
</ItemGroup>
Visual Studio C++ プロジェクト システムでは現在、プロジェクト項目でのマクロをサポートしていません。
<ItemGroup>
<ClCompile Include="$(IntDir)\generated.cpp"> <!--not guaranteed to work in all scenarios-->
</ItemGroup>
参照は ItemGroup で指定され、次のような制限があります。
参照では、条件をサポートしていません。
参照のメタデータでは、条件をサポートしていません。
Import の Microsoft.Cpp.targets 要素
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
ビルド、クリーンなどの C++ ターゲットを (直接、またはインポートを介して) 定義します。
ImportGroup の ExtensionTargets 要素
<ImportGroup Label="ExtensionTargets" />
このグループには、ビルド カスタマイズのターゲット ファイルのインポートが含まれます。
順序が正しくない場合の結果
Visual Studio IDE の動作は、プロジェクト ファイルが前に説明した順序になっていることに依存します。 たとえば、プロパティ ページでプロパティの値を定義すると、IDE は一般に、ラベルが空であるプロパティ グループにそのプロパティの定義を配置します。 この順序より、システム プロパティ シートで取り込まれた既定値が、ユーザー定義の値によって確実にオーバーライドされます。 同様に、ターゲット ファイルは、それより前に定義されているプロパティを使用し、一般にそれ自体ではプロパティを定義していないため、最後にインポートされます。 同じように、ユーザー プロパティ シートはシステム プロパティ シートの後でインポートされます (Microsoft.Cpp.props
によってインクルードされます)。 この順序により、ユーザーはシステム プロパティ シートによって取り込まれたすべての既定値をオーバーライドできます。
.vcxproj
ファイルがこのレイアウトに従っていない場合、意図したビルド結果にならない可能性があります。 たとえば、誤ってユーザー定義のプロパティ シートの後でシステム プロパティ シートをインポートした場合、ユーザーの設定はシステム プロパティ シートによってオーバーライドされます。
IDE のデザイン時のエクスペリエンスも、要素の正しい順序にある程度依存します。 たとえば、.vcxproj
ファイルに PropertySheets
インポート グループがない場合、IDE は、ユーザーがプロパティ マネージャーで作成した新しいプロパティ シートを配置する場所を決定できない可能性があります。 その結果、ユーザーのシートがシステムのシートによってオーバーライドされる場合があります。 IDE によって使用されるヒューリスティックは、.vcxproj
ファイルのレイアウトの小さな不整合は許容できますが、この記事でこれまでに示した構造から外れないようにすることを強くお勧めします。
IDE が要素のラベルを使用する方法
IDE では、全般プロパティ ページで UseOfAtl プロパティを設定すると、プロジェクト ファイルの Configuration プロパティ グループに書き込まれます。 同じプロパティ ページの TargetName プロパティは、ラベルのない構成ごとのプロパティ グループに書き込まれます。 Visual Studio は、プロパティ ページの xml ファイルで、各プロパティを書き込む場所についての情報を取得します。 [全般] プロパティ ページでは (Visual Studio 2019 Enterprise Edition の英語版を使用しているとした場合)、そのファイルは %ProgramFiles(x86)%\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\VC\VCTargets\1033\general.xml
です。 プロパティ ページの XML 規則ファイルでは、Rule とそのすべてのプロパティに関する静的な情報が定義されています。 そのような情報の 1 つは、書き込み先ファイル (その値が書き込まれるファイル) での Rule プロパティの優先位置です。 優先位置は、プロジェクト ファイルの要素の Label 属性によって指定されます。
プロパティ シートのレイアウト
次の XML スニペットは、プロパティ シート (.props) ファイルの最小限のレイアウトです。 .vcxproj
ファイルに似ており、.props
の要素の機能は、これまでの説明から推測できるものです。
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ImportGroup Label="PropertySheets" />
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<ItemDefinitionGroup />
<ItemGroup />
</Project>
独自のプロパティ シートを作成するには、VCTargets
フォルダー内の .props
ファイルの 1 つをコピーし、目的に応じて変更します。 Visual Studio 2019 Enterprise Edition の場合、VCTargets
の既定のパスは %ProgramFiles%\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\VC\VCTargets
です。
関連項目
Visual Studio で C++ コンパイラとビルド プロパティを設定する
プロパティ ページの XML ファイル
.vcxproj
ファイルとワイルドカード