次の方法で共有


MSBuild でプロジェクトをビルドする方法

MSBuild は、ほとんどの Visual Studio プロジェクトをビルドするために使用される Microsoft のビルド エンジンです。 MSBuild は、コンパイラやその他のツールを呼び出してコードをビルドしますが、柔軟な構成とカスタマイズのオプション、コンパイル済みのバイナリだけでなく、他のさまざまな出力成果物を作成するためのインフラストラクチャも含まれています。 MSBuild は非常に構成可能でカスタマイズ可能ですが、このカスタマイズ性を最大限に活用するには、MSBuild のしくみを理解することが重要です。 この記事では、Visual Studio から呼び出された場合でも、コマンド ラインまたはスクリプトから呼び出された場合でも、MSBuild がプロジェクト ファイルを処理する方法について説明します。 MSBuild のしくみを理解すると、問題の診断を改善し、ビルド プロセスをより適切にカスタマイズするのに役立ちます。 この記事では、ビルド プロセスについて説明し、主にすべてのプロジェクトの種類に適用できます。

完全なビルド プロセスは、次の要素で構成されます。

  • 初期スタートアップ - コマンド ライン オプションの処理。
  • evaluation - MSBuild プロジェクト ファイルのテキストの解釈と処理。
  • execution - プロジェクトをビルドするターゲットとタスクを実行します。

外部インポートでは、ソース ファイルやその他の入力成果物に加えて、Microsoft.Common.targets などの標準インポートと、ソリューションまたはプロジェクト レベルでのユーザーが構成可能なインポートの両方を含む、ビルド プロセスの詳細が定義されます。

Startup

MSBuild は、 Microsoft.Build.dllの MSBuild オブジェクト モデルを介して Visual Studio から呼び出すか、実行可能ファイル (MSBuild.exe または dotnet build) をコマンド ラインで直接呼び出すか、CI システムなどのスクリプトで呼び出すことができます。 どちらの場合も、ビルド プロセスに影響を与える入力には、プロジェクト ファイル (または Visual Studio 内部のプロジェクト オブジェクト)、場合によってはソリューション ファイル、環境変数、コマンド ライン スイッチ、または同等のオブジェクト モデルが含まれます。 スタートアップ フェーズでは、ロガーの構成などの MSBuild 設定を構成するために、コマンド ライン オプションまたはオブジェクト モデルに相当するものが使用されます。 コマンド ラインで -property または -p スイッチを使用して設定されたプロパティはグローバル プロパティとして設定されます。グローバル プロパティは、プロジェクト ファイルが後で読み取られる場合でも、プロジェクト ファイルで設定される値をオーバーライドします。

次のセクションでは、ソリューション ファイルやプロジェクト ファイルなどの入力ファイルについて説明します。

ソリューションとプロジェクト

MSBuild インスタンスは、1 つのプロジェクトまたはソリューションの一部として多数のプロジェクトで構成される場合があります。 .slnx形式または.sln形式のソリューション ファイルの両方がサポートされています (MSBuild 17.12 以降)。 ソリューション ファイル (.sln) は MSBuild XML ファイルではありませんが、MSBuild は、特定の構成とプラットフォーム設定用にビルドする必要があるすべてのプロジェクトを認識するように解釈します。 MSBuild がこの入力を処理すると、ソリューション ビルドと呼ばれます。 すべてのソリューション ビルドで何かを実行できる拡張可能なポイントがいくつかありますが、このビルドは個々のプロジェクト ビルドとは別の実行であるため、ソリューション ビルドのプロパティやターゲット定義の設定は各プロジェクト ビルドに関連しません。

ソリューション ビルドを拡張する方法については、ソリューション ビルドの カスタマイズに関する説明をご覧ください

Visual Studio ビルドと MSBuild.exe ビルド

Visual Studio でプロジェクトをビルドする場合と、MSBuild 実行可能ファイルを使用して MSBuild を直接呼び出す場合、または MSBuild オブジェクト モデルを使用してビルドを開始する場合には、いくつかの大きな違いがあります。 Visual Studio は、Visual Studio ビルドのプロジェクトのビルド順序を管理します。MSBuild は個々のプロジェクト レベルでのみ呼び出され、呼び出されると、MSBuild の動作に大きな影響を与えるいくつかのブール型プロパティ (BuildingInsideVisualStudioBuildProjectReferences) が設定されます。 各プロジェクト内では、実行は MSBuild を介して呼び出された場合と同じように行われますが、参照されるプロジェクトとの違いが生じます。 MSBuild では、参照先のプロジェクトが必要な場合は、ビルドが実際に発生します。つまり、タスクとツールを実行し、出力を生成します。 Visual Studio ビルドで参照先プロジェクトが見つかると、MSBuild は参照先プロジェクトからの期待される出力のみを返します。これにより、Visual Studio はこれらの他のプロジェクトのビルドを制御できます。 Visual Studio は、ビルド順序を決定し、必要に応じて MSBuild を個別に呼び出します。すべて Visual Studio の制御下にあります。

もう 1 つの違いは、MSBuild がソリューション ファイルを使用して呼び出されたとき、MSBuild がソリューション ファイルを解析し、標準の XML 入力ファイルを作成して評価し、プロジェクトとして実行する場合です。 ソリューション ビルドは、プロジェクトの前に実行されます。 Visual Studio からビルドする場合、この処理は行われません。MSBuild ではソリューション ファイルが表示されません。 その結果、ソリューション ビルドのカスタマイズ ( 以前に使用) が行われます。SolutionName.sln.targets 以降 。SolutionName.sln.targets) は、Visual Studio ビルドではなく、MSBuild.exe、 dotnet build、またはオブジェクト モデル駆動型ビルドにのみ適用されます。

Project SDK

MSBuild プロジェクト ファイルの SDK 機能は比較的新しい機能です。 この変更の前に、プロジェクト ファイルは、特定のプロジェクトの種類のビルド プロセスを定義した .targets ファイルと .props ファイルを明示的にインポートしました。

.NET Core プロジェクトは、適切なバージョンの .NET SDK をインポートします。 概要、 .NET Core プロジェクト SDK、および プロパティへの参照を参照してください。

評価フェーズ

このセクションでは、これらの入力ファイルを処理および解析して、ビルドされる内容を決定するメモリ内オブジェクトを生成する方法について説明します。

評価フェーズの目的は、入力 XML ファイルとローカル環境に基づいて、メモリ内にオブジェクト構造を作成することです。 評価フェーズは、プロジェクト XML ファイルなどの入力ファイルを処理する 6 つのパスで構成されます。インポートされた XML ファイルは、主にプロパティを設定するか、ビルド ターゲットを定義するかに応じて、通常は .props ファイルまたは .targets ファイルとして名前が付けられます。 各パスは、後で実行フェーズでプロジェクトをビルドするために使用されるメモリ内オブジェクトの一部をビルドしますが、評価フェーズでは実際のビルド アクションは発生しません。 各パス内で、要素は表示される順序で処理されます。

評価フェーズのパスは次のとおりです。

  • 環境変数を評価する
  • インポートとプロパティを評価する
  • 項目定義を評価する
  • アイテムを評価する
  • UsingTask 要素を評価する
  • ターゲットを評価する

インポートとプロパティは、一連の外観で同じパスで評価されます。これは、インポートが所定の位置に展開されている場合と同じです。 したがって、以前にインポートしたファイルのプロパティ設定は、後でインポートされたファイル内で使用できます。

これらのパスの順序は大きな影響を与え、プロジェクト ファイルをカスタマイズするときに知っておくべき重要です。 「プロパティと項目の評価順序」を参照してください。

環境変数を評価する

このフェーズでは、環境変数を使用して同等のプロパティを設定します。 たとえば、PATH 環境変数はプロパティ $(PATH)として使用できます。 コマンド ラインまたはスクリプトから実行すると、コマンド環境は通常どおりに使用され、Visual Studio から実行すると、Visual Studio の起動時に有効な環境が使用されます。

インポートとプロパティを評価する

このフェーズでは、プロジェクト ファイルとインポートのチェーン全体を含め、入力 XML 全体が読み込まれます。 MSBuild は、プロジェクトの XML とインポートされたすべてのファイルを表すインメモリ XML 構造を作成します。 現時点では、ターゲットにないプロパティが評価され、設定されます。

MSBuild がプロセスの早い段階ですべての XML 入力ファイルを読み取った結果、ビルド プロセス中にこれらの入力に対する変更が現在のビルドに影響することはありません。

ターゲットの外部のプロパティは、ターゲット内のプロパティとは異なる方法で処理されます。 このフェーズでは、ターゲットの外部で定義されているプロパティのみが評価されます。

プロパティは渡されるプロパティの順序で処理されるため、入力内の任意の時点のプロパティは、入力の前に表示されるプロパティ値にアクセスできますが、後で表示されるプロパティにはアクセスできません。

プロパティは項目が評価される前に処理されるため、プロパティのパスのどの部分でも項目の値にアクセスできません。

項目定義を評価する

このフェーズでは、 項目定義 が解釈され、これらの定義のメモリ内表現が作成されます。

アイテムを評価する

ターゲット内で定義された項目は、ターゲット外の項目とは異なる方法で処理されます。 このフェーズでは、ターゲットの外部にある項目とそれに関連付けられているメタデータが処理されます。 項目定義によって設定されたメタデータは、項目に設定されたメタデータによってオーバーライドされます。 アイテムは表示順に処理されるため、前に定義した項目を参照できますが、後で表示されるアイテムは参照できません。 渡される項目はプロパティのパスの後にあるため、後でプロパティ定義が表示されるかどうかに関係なく、ターゲットの外部で定義されている場合、アイテムは任意のプロパティにアクセスできます。

UsingTask要素を評価する

このフェーズでは、 UsingTask 要素が読み取られ、タスクは実行フェーズ中に後で使用できるように宣言されます。

ターゲットを評価する

このフェーズでは、実行の準備として、すべてのターゲット オブジェクト構造がメモリ内に作成されます。 実際の実行は行われません。

実行フェーズ

実行フェーズでは、ターゲットが順序付けされて実行され、すべてのタスクが実行されます。 ただし、最初に、ターゲット内で定義されているプロパティと項目は、表示される順序で 1 つのフェーズでまとめて評価されます。 処理の順序は、ターゲットに含まれていないプロパティと項目の処理方法とは特に異なります。最初にすべてのプロパティ、次にすべてのアイテムが個別のパスで処理されます。 ターゲット内のプロパティと項目の変更は、ターゲットが変更された後に確認できます。

ターゲットのビルド順序

1 つのプロジェクトで、ターゲットが順次実行されます。 中心的な問題は、依存関係を使用して適切な順序でターゲットを構築するために、すべてをビルドする順序を決定する方法です。

ターゲットのビルド順序は、各ターゲットの BeforeTargetsDependsOnTargets、および AfterTargets 属性の使用によって決まります。 以前のターゲットがこれらの属性で参照されているプロパティを変更した場合、以前のターゲットの実行中に、後のターゲットの順序が影響を受ける可能性があります。

順序付けの規則については、「 ターゲット ビルド順序の決定」を参照してください。 プロセスは、ビルドするターゲットを含むスタック構造によって決定されます。 このタスクの先頭にあるターゲットが実行を開始し、他に依存している場合は、それらのターゲットがスタックの一番上にプッシュされ、実行が開始されます。 依存関係のないターゲットがある場合は、完了まで実行され、親ターゲットが再開されます。

プロジェクト参照

MSBuild で実行できるコード パスには、ここで説明する通常のパスと、次のセクションで説明するグラフ オプションの 2 つがあります。

個々のプロジェクトは、 ProjectReference 項目を通じて他のプロジェクトへの依存を指定します。 スタックの上部にあるプロジェクトがビルドを開始すると、 ResolveProjectReferences ターゲットが実行される時点に達します。これは、共通のターゲット ファイルで定義されている標準ターゲットです。

ResolveProjectReferences は、 ProjectReference 項目の入力を使用して MSBuild タスクを呼び出して出力を取得します。 ProjectReference項目は、Referenceなどのローカル項目に変換されます。 現在のプロジェクトの MSBuild 実行フェーズは、実行フェーズが参照先プロジェクトの処理を開始している間に一時停止します (評価フェーズは必要に応じて最初に行われます)。 参照先のプロジェクトは、依存プロジェクトのビルドを開始した後にのみビルドされるため、ビルドするプロジェクトのツリーが作成されます。

Visual Studio では、ソリューション (.sln) ファイルにプロジェクトの依存関係を作成できます。 依存関係はソリューション ファイルで指定され、ソリューションをビルドするとき、または Visual Studio 内でビルドする場合にのみ考慮されます。 1 つのプロジェクトをビルドする場合、この種類の依存関係は無視されます。 ソリューション参照は MSBuild によって ProjectReference 項目に変換され、その後も同じ方法で処理されます。

グラフ オプション

グラフ ビルド スイッチ (-graphBuild または -graph) を指定すると、 ProjectReference は MSBuild で使用される最上位の概念になります。 MSBuild は、すべてのプロジェクトを解析し、ビルド順序グラフ (プロジェクトの実際の依存関係グラフ) を構築します。これは、ビルド順序を決定するために走査されます。 個々のプロジェクトのターゲットと同様に、MSBuild では、参照されるプロジェクトが依存するプロジェクトの後にビルドされることが保証されます。

並列実行

マルチプロセッサ サポート (-maxCpuCount または -m スイッチ) を使用する場合、MSBuild はノードを作成します。これは、使用可能な CPU コアを使用する MSBuild プロセスです。 各プロジェクトは、使用可能なノードに送信されます。 ノード内では、個々のプロジェクト ビルドが順次実行されます。

タスクは、MSBuild の $(BuildInParallel) プロパティの値に従って設定されるブール変数BuildInParallelを設定することで、並列実行を有効にすることができます。 並列実行が有効になっているタスクの場合、作業スケジューラはノードを管理し、ノードに作業を割り当てます。

MSBuild を使用した複数のプロジェクトの並列ビルドを参照してください

標準インポート

Microsoft.Common.propsMicrosoft.Common.targets は、両方とも .NET プロジェクト ファイル (SDK スタイルのプロジェクトでは明示的または暗黙的) によってインポートされ、Visual Studio インストールの MSBuild\Current\bin フォルダーにあります。 C++ プロジェクトには、独自のインポート階層があります。 C++ プロジェクトの MSBuild Internals を参照してください。

Microsoft.Common.props ファイル セットの既定値は、オーバーライドできます。 プロジェクト ファイルの先頭に (明示的または暗黙的に) インポートされます。 そうすることで、プロジェクトの設定が既定値の後に表示され、上書きされます。

Microsoft.Common.targets ファイルとインポートするターゲット ファイルは、.NET プロジェクトの標準ビルド プロセスを定義します。 また、ビルドのカスタマイズに使用できる拡張ポイントも提供されます。

実装では、 Microsoft.Common.targets、Microsoft.Common.CurrentVersion.targets をインポートするシン ラッパーです。 このファイルには、標準プロパティの設定が含まれており、ビルド プロセスを定義する実際のターゲットが定義されています。 Buildターゲットはここで定義されていますが、実際には空です。 ただし、Build ターゲットには、実際のビルド ステップを構成する個々のターゲット (BeforeBuildCoreBuildAfterBuild) を指定するDependsOnTargets属性が含まれています。 Buildターゲットは次のように定義されます。

  <PropertyGroup>
    <BuildDependsOn>
      BeforeBuild;
      CoreBuild;
      AfterBuild
    </BuildDependsOn>
  </PropertyGroup>

  <Target
      Name="Build"
      Condition=" '$(_InvalidConfigurationWarning)' != 'true' "
      DependsOnTargets="$(BuildDependsOn)"
      Returns="@(TargetPathWithTargetPlatformMoniker)" />

BeforeBuild および AfterBuild は拡張ポイントです。 これらは Microsoft.Common.CurrentVersion.targets ファイルでは空ですが、プロジェクトは、メイン ビルド プロセスの前または後に実行する必要があるタスクを含む独自のBeforeBuildAfterBuildターゲットを提供できます。 AfterBuildは、Build ターゲットのDependsOnTargets属性にAfterBuildが表示されますが、CoreBuild後に発生するため、no-op ターゲット (Build) の前に実行されます。

CoreBuild ターゲットには、次のようにビルド ツールの呼び出しが含まれています。

  <PropertyGroup>
    <CoreBuildDependsOn>
      BuildOnlySettings;
      PrepareForBuild;
      PreBuildEvent;
      ResolveReferences;
      PrepareResources;
      ResolveKeySource;
      Compile;
      ExportWindowsMDFile;
      UnmanagedUnregistration;
      GenerateSerializationAssemblies;
      CreateSatelliteAssemblies;
      GenerateManifests;
      GetTargetPath;
      PrepareForRun;
      UnmanagedRegistration;
      IncrementalClean;
      PostBuildEvent
    </CoreBuildDependsOn>
  </PropertyGroup>
  <Target
      Name="CoreBuild"
      DependsOnTargets="$(CoreBuildDependsOn)">

    <OnError ExecuteTargets="_TimeStampAfterCompile;PostBuildEvent" Condition="'$(RunPostBuildEvent)'=='Always' or '$(RunPostBuildEvent)'=='OnOutputUpdated'"/>
    <OnError ExecuteTargets="_CleanRecordFileWrites"/>

  </Target>

次の表では、これらのターゲットについて説明します。一部のターゲットは、特定のプロジェクトの種類にのみ適用されます。

目標 Description
BuildOnlySettings Visual Studio によってプロジェクトの読み込み時に MSBuild が呼び出されたときではなく、実際のビルドのみの設定。
PrepareForBuild ビルドの前提条件を準備する
PreBuildEvent ビルド前に実行するタスクを定義するプロジェクトの拡張ポイント
ResolveProjectReferences プロジェクトの依存関係を分析し、参照されるプロジェクトをビルドする
ResolveAssemblyReferences 参照されるアセンブリを検索します。
ResolveReferences すべての依存関係を見つけるための ResolveProjectReferencesResolveAssemblyReferences で構成されます
PrepareResources リソース ファイルの処理
ResolveKeySource アセンブリの署名に使用される厳密な名前キーと、 ClickOnce マニフェストの署名に使用される証明書を解決します。
コンパイル コンパイラを呼び出します
ExportWindowsMDFile コンパイラによって生成された WinMDModule ファイルから WinMD ファイルを生成します。
UnmanagedUnregistration 以前のビルドから COM 相互運用機能 レジストリ エントリを削除またはクリーンアップする
GenerateSerializationAssemblies sgen.exeを使用して XML シリアル化アセンブリを生成します。
CreateSatelliteAssemblies リソース内の一意のカルチャごとに 1 つのサテライト アセンブリを作成します。
マニフェストの生成 ClickOnce アプリケーション マニフェストと配置マニフェストまたはネイティブ マニフェストを生成します。
GetTargetPath メタデータを含む、このプロジェクトのビルド製品 (実行可能ファイルまたはアセンブリ) を含む項目を返します。
PrepareForRun ビルド出力が変更された場合は、最終的なディレクトリにコピーします。
UnmanagedRegistration COM 相互運用機能のレジストリ エントリを設定する
IncrementalClean 以前のビルドで生成されたものの、現在のビルドでは生成されなかったファイルを削除します。 これは、インクリメンタル ビルドで Clean 作業を行うために必要です。
PostBuildEvent ビルド後に実行するタスクを定義するプロジェクトの拡張ポイント

前の表のターゲットの多くは、 Microsoft.CSharp.targets などの言語固有のインポートで見つかります。 このファイルは、C# .NET プロジェクトに固有の標準ビルド プロセスの手順を定義します。 たとえば、C# コンパイラを実際に呼び出す Compile ターゲットが含まれています。

ユーザーが構成可能なインポート

標準インポートに加えて、ビルド プロセスをカスタマイズするために追加できるインポートがいくつかあります。

  • Directory.Build.props
  • Directory.Build.targets

これらのファイルは、その下にあるサブフォルダー内のすべてのプロジェクトの標準インポートによって読み込まれます。 これは一般的に、ソリューション内のすべてのプロジェクトを制御するための設定のソリューション レベルですが、ドライブのルートまで、ファイル システム内で上位になる可能性もあります。

Directory.Build.props ファイルは Microsoft.Common.props によってインポートされるため、そこに定義されているプロパティはプロジェクト ファイルで使用できます。 プロジェクト ファイルで再定義して、プロジェクトごとに値をカスタマイズできます。 Directory.Build.targets ファイルは、プロジェクト ファイルの後に読み込まれます。 通常はターゲットが含まれますが、ここでは、個々のプロジェクトで再定義したくないプロパティを定義することもできます。

プロジェクト ファイル内のカスタマイズ

ソリューション エクスプローラー、プロパティ ウィンドウ、またはプロジェクト プロパティで変更を行うと、Visual Studio によってプロジェクト ファイルが更新されますが、プロジェクト ファイルを直接編集して独自の変更を加えることもできます。

多くのビルド動作は、MSBuild プロパティを設定することによって構成できます。MSBuild プロパティは、プロジェクトファイル内でプロジェクトに対してローカルに設定するか、前のセクションで説明したように、プロジェクトとソリューションのフォルダー全体に対してプロパティをグローバルに設定する Directory.Build.props ファイルを作成することで構成できます。 コマンド ラインまたはスクリプト上のアドホック ビルドの場合は、コマンド ラインの /p オプションを使用して、MSBuild の特定の呼び出しのプロパティを設定することもできます。 設定できるプロパティについては、 一般的な MSBuild プロジェクト のプロパティを参照してください。