チュートリアル: MSBuild プロジェクト ファイルのゼロからの作成
.NET Framework を対象とするプログラミング言語は、MSBuild プロジェクト ファイルを使用してアプリケーションのビルド プロセスを記述および制御します。 Visual Studio を使用して MSBuild プロジェクト ファイルを作成すると、適切な XML が自動的に追加されますが、 その XML がどのように構成されているかや、それに変更を加えてビルドを制御するにはどうすればよいかを知っておくことも有用です。
Note
この記事は、MSBuild が SDK に依存せずに動作するしくみの基礎を学習する場合に適しています。 dotnet build
を使用するときや、Sdk
属性をルート プロジェクト要素に追加するときなど、SDK によるビルドはこの記事では取り上げていません。 「.NET プロジェクト SDK」を参照してください。
C++ プロジェクトのプロジェクト ファイルを作成する方法の詳細については、「MSBuild (C++)」をご覧ください。
このチュートリアルでは、テキスト エディターのみを使用して、基本的なプロジェクト ファイルをインクリメント方式で作成する方法について説明します。 このチュートリアルの手順を以下に示します。
PATH 環境変数を拡張します。
最低限の内容のみを含むアプリケーション ソース ファイルを作成します。
最低限の内容のみを含む MSBuild プロジェクト ファイルを作成します。
プロジェクト ファイルを使用してアプリケーションをビルドします。
ビルドを制御するためのプロパティを追加します。
プロパティの値を変更してビルドを制御します。
ビルド ターゲットを追加します。
ターゲットを指定してビルドを制御します。
インクリメンタル ビルド」を参照してください。
このチュートリアルでは、コマンド プロンプトでプロジェクトをビルドして結果を確認する方法を説明します。 MSBuild の詳細および MSBuild をコマンド プロンプトで実行する方法の詳細については、「チュートリアル: MSBuild の使用」をご覧ください。
このチュートリアルを実行するには、Visual Studio がインストールされている必要があります。Visual Studio には、このチュートリアルに必要な MSBuild と C# コンパイラが含まれています。
パスを拡張する
MSBuild を使用するには、必要なすべてのツールが含まれるように PATH 環境変数を拡張する必要があります。 Visual Studio 用開発者コマンド プロンプトを使用できます。 これは、Windows 10 上の Windows タスク バーの検索ボックスで検索してください。 通常のコマンド プロンプトまたはスクリプト環境で環境を設定するには、Visual Studio インストールの Common7/Tools サブフォルダーで VSDevCmd.bat を実行します。
最低限の内容のみを含むアプリケーションを作成する
ここでは、最低限の内容のみを含む C# アプリケーション ソース ファイルをテキスト エディターで作成する方法を説明します。
コマンド プロンプトで、アプリケーションを作成するフォルダーに移動します (\My Documents\、\Desktop\ など)。
\HelloWorld\ という名前のサブフォルダーを作成し、その中に入るようにディレクトリを変更します。
テキスト エディターで、新しいファイル HelloWorld.cs を作成し、次のコードをコピーして貼り付けます。
using System; class HelloWorld { static void Main() { #if DebugConfig Console.WriteLine("WE ARE IN THE DEBUG CONFIGURATION"); #endif Console.WriteLine("Hello, world!"); } }
コマンド プロンプトで「csc helloworld.cs」と入力して、アプリケーションをビルドします。
コマンド プロンプトで「helloworld」と入力して、アプリケーションをテストします。
"Hello, world!" というメッセージが表示されます。
実行可能ファイルを削除します。
最低限の内容のみを含む MSBuild プロジェクト ファイルを作成する
最低限の内容のみを含むアプリケーション ソース ファイルを作成できたので、次に、そのアプリケーションをビルドするための最低限の内容のみを含むプロジェクト ファイルを作成します。 このプロジェクト ファイルに含まれる要素は次のとおりです。
必須のルート
Project
ノード項目要素を格納する
ItemGroup
ノードアプリケーション ソース ファイルを参照する項目要素
アプリケーションをビルドするために必要なタスクを格納する
Target
ノードアプリケーションをビルドするために C# コンパイラを起動する
Task
要素。
最低限の内容のみを含む MSBuild プロジェクト ファイルを作成するには
テキスト エディターで、新しいファイル HelloWorld.csproj を作成し、次のコードを入力します。
<Project> <ItemGroup> <Compile Include="helloworld.cs" /> </ItemGroup> </Project>
この
ItemGroup
には項目要素Compile
が含まれ、項目としてソース ファイルが 1 つ指定されます。Target
ノードの子要素としてProject
ノードを追加します。 そのノードにBuild
という名前を付けます。<Target Name="Build"> </Target>
次のタスク要素を
Target
ノードの子要素として挿入します。<Csc Sources="@(Compile)"/>
このプロジェクト ファイルを Helloworld.csproj という名前で保存します。
最低限の内容のみを含むプロジェクト ファイルが完成すると、コードが次のようになります。
<Project>
<ItemGroup>
<Compile Include="helloworld.cs"/>
</ItemGroup>
<Target Name="Build">
<Csc Sources="@(Compile)"/>
</Target>
</Project>
Build ターゲットのタスクは順番に実行されます。 ここでは、C# コンパイラの Csc
タスクが唯一のタスクです。 このタスクは、コンパイルするソース ファイルのリストを受け取ります。これは、Compile
項目の値によって渡されます。 Compile
項目は、Helloworld.cs という 1 つのソース ファイルのみを参照しています。
Note
次のように、項目要素でワイルドカード文字のアスタリスク (*) を使用すると、ファイル名拡張子が .cs であるすべてのファイルを参照できます。
<Compile Include="*.cs" />
アプリケーションのビルド
次に、先ほど作成したプロジェクト ファイルを使用してアプリケーションをビルドします。
コマンド プロンプトで、「msbuild helloworld.csproj -t:Build」と入力します。
C# コンパイラが呼び出され、Helloworld プロジェクト ファイルの Build ターゲットがビルドされて、Helloworld アプリケーションが作成されます。
「helloworld」と入力してアプリケーションをテストします。
"Hello, world!" というメッセージが表示されます。
Note
詳細レベルを上げると、ビルドの詳細情報を表示できます。 詳細レベルを "detailed" に設定するには、コマンド プロンプトで次のコマンドを入力します。
msbuild helloworld.csproj -t:Build -verbosity:detailed
ビルド プロパティを追加する
プロジェクト ファイルにビルド プロパティを追加すると、ビルドをさらに細かく制御できます。 ここでは、次のプロパティを追加します。
アプリケーションの名前を指定する
AssemblyName
プロパティアプリケーションを格納するフォルダーを指定する
OutputPath
プロパティ
ビルド プロパティを追加するには
既存のアプリケーション実行可能ファイルを削除します (後で、
Clean
ターゲットを追加し、古い出力ファイルの削除を処理します)。プロジェクト ファイルで、次の
PropertyGroup
要素を開始Project
要素の直後に挿入します。<PropertyGroup> <AssemblyName>MSBuildSample</AssemblyName> <OutputPath>Bin\</OutputPath> </PropertyGroup>
次のタスクを Build ターゲットの
Csc
タスクの直前に追加します。<MakeDir Directories="$(OutputPath)" Condition="!Exists('$(OutputPath)')" />
この
MakeDir
タスクは、OutputPath
プロパティによって指定されるフォルダーを、同名のフォルダーが存在しない場合に作成します。次の
OutputAssembly
属性をCsc
タスクに追加します。<Csc Sources="@(Compile)" OutputAssembly="$(OutputPath)$(AssemblyName).exe" />
この属性は、C# コンパイラに対して、
AssemblyName
プロパティによって指定されるアセンブリを生成し、OutputPath
プロパティによって指定されるフォルダーに配置するように指定します。変更を保存します。
プロジェクト ファイルのコードが次のようになります。
<Project>
<PropertyGroup>
<AssemblyName>MSBuildSample</AssemblyName>
<OutputPath>Bin\</OutputPath>
</PropertyGroup>
<ItemGroup>
<Compile Include="helloworld.cs" />
</ItemGroup>
<Target Name="Build">
<MakeDir Directories="$(OutputPath)" Condition="!Exists('$(OutputPath)')" />
<Csc Sources="@(Compile)" OutputAssembly="$(OutputPath)$(AssemblyName).exe" />
</Target>
</Project>
Note
パス区切り記号の円記号 (\) は、Csc
タスクの OutputAssembly
属性に追加するのではなく、OutputPath
要素で指定するフォルダー名の末尾に追加することをお勧めします。 次に例を示します。
<OutputPath>Bin\</OutputPath>
OutputAssembly="$(OutputPath)$(AssemblyName).exe" />
この形式が次の形式より推奨されます。
<OutputPath>Bin</OutputPath>
OutputAssembly="$(OutputPath)\$(AssemblyName).exe" />
ビルド プロパティをテストする
次に、ビルド プロパティで出力フォルダーとアプリケーション名を指定したプロジェクト ファイルを使用してアプリケーションをビルドします。
コマンド プロンプトで、「msbuild helloworld.csproj -t:Build」と入力します。
\Bin フォルダーが作成され、C# コンパイラが呼び出されて、MSBuildSample アプリケーションが作成されて \Bin\ フォルダーに配置されます。
「dir Bin」と入力して、\Bin\ フォルダーが作成されていることと、そこに MSBuildSample アプリケーションが含まれていることを確認します。
「Bin\MSBuildSample」と入力して実行可能ファイルを実行し、アプリケーションをテストします。
"Hello, world!" というメッセージが表示されます。
ビルド ターゲットを追加する
次に、次の 2 つのターゲットをプロジェクト ファイルに追加します。
古いファイルを削除する Clean ターゲット
DependsOnTargets
属性を使用して Build タスクの前に強制的に Clean タスクを実行する Rebuild ターゲット
ターゲットが複数になるので、Build ターゲットを既定のターゲットに設定します。
ビルド ターゲットを追加するには
プロジェクト ファイルで、Build ターゲットの直後に次の 2 つのターゲットを追加します。
<Target Name="Clean" > <Delete Files="$(OutputPath)$(AssemblyName).exe" /> </Target> <Target Name="Rebuild" DependsOnTargets="Clean;Build" />
Clean ターゲットは、Delete タスクを呼び出してアプリケーションを削除します。 Rebuild ターゲットは、Clean ターゲットと Build ターゲットの両方が実行されるまで実行されません。 Rebuild ターゲットにはタスクは含まれていませんが、このターゲットにより、Build ターゲットの前に Clean ターゲットが実行されるようになります。
次の
DefaultTargets
属性を開始Project
要素に追加します。<Project DefaultTargets="Build">
これにより、Build ターゲットが既定のターゲットに設定されます。
プロジェクト ファイルのコードが次のようになります。
<Project DefaultTargets="Build">
<PropertyGroup>
<AssemblyName>MSBuildSample</AssemblyName>
<OutputPath>Bin\</OutputPath>
</PropertyGroup>
<ItemGroup>
<Compile Include="helloworld.cs" />
</ItemGroup>
<Target Name="Build">
<MakeDir Directories="$(OutputPath)" Condition="!Exists('$(OutputPath)')" />
<Csc Sources="@(Compile)" OutputAssembly="$(OutputPath)$(AssemblyName).exe" />
</Target>
<Target Name="Clean" >
<Delete Files="$(OutputPath)$(AssemblyName).exe" />
</Target>
<Target Name="Rebuild" DependsOnTargets="Clean;Build" />
</Project>
ビルド ターゲットをテストする
新しいビルド ターゲットを使用して、プロジェクト ファイルの以下の機能をテストします。
既定のビルドをビルドする。
コマンド プロンプトでアプリケーション名を設定する。
別のアプリケーションをビルドする前にアプリケーションを削除する。
別のアプリケーションをビルドせずにアプリケーションを削除する。
ビルド ターゲットをテストするには
コマンド プロンプトで、「msbuild helloworld.csproj -p:AssemblyName=Greetings」と入力します。
-t スイッチを使用してターゲットを明示的に設定していないため、MSBuild により既定の Build ターゲットがビルドされます。 -p スイッチでは、
AssemblyName
プロパティをオーバーライドして新しい値Greetings
を割り当てています。 これにより、Greetings.exe という新しいアプリケーションが \Bin\ フォルダーに作成されます。「dir Bin」と入力して、\Bin\ フォルダーに MSBuildSample アプリケーションと新しい Greetings アプリケーションの両方が含まれていることを確認します。
Greetings アプリケーションをテストします (たとえば、Windows で「Bin\Greetings」と入力します)。
"Hello, world!" というメッセージが表示されます。
「msbuild helloworld.csproj -t:clean」を入力して、MSBuildSample アプリケーションを削除します。
Clean タスクが実行されて、
AssemblyName
プロパティの値が既定値のMSBuildSample
になっているアプリケーションが削除されます。「msbuild helloworld.csproj -t:clean -p:AssemblyName=Greetings」を入力して、Greetings アプリケーションを削除します。
Clean タスクが実行されて、AssemblyName プロパティの値が、指定した値
Greetings
になっているアプリケーションが削除されます。「dir Bin」と入力して、\Bin\ フォルダーが空になったことを確認します。
「msbuild」と入力します。
プロジェクト ファイルが指定されていませんが、現在のフォルダーにはプロジェクト ファイルが 1 つしかないため、helloworld.csproj ファイルがビルドされます。 その結果、MSBuildSample アプリケーションが \Bin\ フォルダーに作成されます。
\Bin\ フォルダーに MSBuildSample アプリケーションが含まれていることを確認するには、「dir Bin」と入力します。
インクリメンタル ビルド
MSBuild では、ターゲットが依存しているソース ファイルやターゲット ファイルが変更された場合にのみターゲットをビルドすることができます。 ファイルが変更されているかどうかはファイルのタイム スタンプを使用して特定されます。
インクリメンタル ビルドを実行するには
プロジェクト ファイルで、開始 Build ターゲットに次の属性を追加します。
Inputs="@(Compile)" Outputs="$(OutputPath)$(AssemblyName).exe"
ここでは、
Compile
項目グループに指定されている入力ファイルに Build ターゲットが依存していること、出力対象がアプリケーション ファイルであることを指定しています。この結果、Build ターゲットのコードは次のようになります。
<Target Name="Build" Inputs="@(Compile)" Outputs="$(OutputPath)$(AssemblyName).exe"> <MakeDir Directories="$(OutputPath)" Condition="!Exists('$(OutputPath)')" /> <Csc Sources="@(Compile)" OutputAssembly="$(OutputPath)$(AssemblyName).exe" /> </Target>
コマンド プロンプトで「msbuild -v:d」と入力して、Build ターゲットをテストします。
helloworld.csproj が既定のプロジェクト ファイルであること、Build が既定のターゲットであることに注意してください。
-v:d スイッチは、前に使用した -verbosity:detailed の省略形です。
既に出力している場合、次のような行が表示されるはずです。
すべての出力ファイルが入力ファイルに対して最新なので、ターゲット "Build" を省略します。
アプリケーションがビルドされてから変更されたソース ファイルがないため、Build ターゲットはスキップされます。
C# の例
次の例は、C# アプリケーションをコンパイルし、出力ファイル名を含むメッセージを記録するプロジェクト ファイルを示しています。
コード
<Project DefaultTargets = "Compile">
<!-- Set the application name as a property -->
<PropertyGroup>
<appname>HelloWorldCS</appname>
</PropertyGroup>
<!-- Specify the inputs by type and file name -->
<ItemGroup>
<CSFile Include = "*.cs"/>
</ItemGroup>
<Target Name="Compile">
<!-- Run the C# compilation using input files of type CSFile -->
<CSC
Sources = "@(CSFile)"
OutputAssembly = "$(appname).exe">
<!-- Set the OutputAssembly attribute of the CSC task
to the name of the executable file that is created -->
<Output
TaskParameter = "OutputAssembly"
ItemName = "EXEFile" />
</CSC>
<!-- Log the file name of the output file -->
<Message Text="The output file is @(EXEFile)"/>
</Target>
</Project>
Visual Basic の例
次の例は、Visual Basic アプリケーションをコンパイルし、出力ファイル名を含むメッセージを記録するプロジェクト ファイルを示しています。
コード
<Project DefaultTargets = "Compile">
<!-- Set the application name as a property -->
<PropertyGroup>
<appname>HelloWorldVB</appname>
</PropertyGroup>
<!-- Specify the inputs by type and file name -->
<ItemGroup>
<VBFile Include = "consolehwvb1.vb"/>
</ItemGroup>
<Target Name = "Compile">
<!-- Run the Visual Basic compilation using input files of type VBFile -->
<VBC
Sources = "@(VBFile)"
OutputAssembly= "$(appname).exe">
<!-- Set the OutputAssembly attribute of the VBC task
to the name of the executable file that is created -->
<Output
TaskParameter = "OutputAssembly"
ItemName = "EXEFile" />
</VBC>
<!-- Log the file name of the output file -->
<Message Text="The output file is @(EXEFile)"/>
</Target>
</Project>
次の内容
このチュートリアルで説明した作業の大半は、Visual Studio で自動的に実行できます。 Visual Studio を使用して MSBuild プロジェクト ファイルを作成、編集、ビルド、およびテストする方法については、「チュートリアル: MSBuild の使用」をご覧ください。