ビルドの自動化に MSBuild を使っているけど、ビルド手順がよく似た複数のプロジェクト*1があるとき、プロジェクト1つ1つにビルドファイルを用意していた。でも、タスクの内容はほとんど同じで、違うのは作業ディレクトリや Subversion のリポジトリ URL くらい。
内容がほとんど同じとはいえ、プロジェクトの数は10個くらいあるので、ビルドファイルを保守するのはちょっと大変。タスクを使い回せないか考えていたら、Import を使う方法が思いついた。
まず、プロジェクトごとに異なる値を PropertyGroup で定義。共通のビルドファイルもインポートしておく。
環境定義用ビルドファイル
<?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="BuildAll" xmlns = "http://schemas.microsoft.com/developer/msbuild/2003"> <!--プロジェクトごとに異なる環境を記述--> <PropertyGroup> <WorkingDirectoryPath>作業フォルダのパス</WorkingDirectoryPath> <BinDirectoryPath>アセンブリの出力先</BinDirectoryPath> <SolutionFilePath>VisualStudioソリューションファイルのパス</SolutionFilePath> <SourceRepositoryUrl>ソースコードのリポジトリ</SourceRepositoryUrl> <BinRepositoryUrl>アセンブリのリポジトリ</BinRepositoryUrl> <CommonBuildFilePath>共通のビルドファイルのパス</CommonBuildFilePath> </PropertyGroup> <!--共通のビルドファイルをインポート--> <Import Project="$(CommonBuildFilePath)"/> </Project>
次にインポートされるビルドファイルを作る。PropertyGroup で定義したプロパティを使ってタスクを記述していく。
共通タスク用ビルドファイル
<?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="BuildAll" xmlns = "http://schemas.microsoft.com/developer/msbuild/2003"> <PropertyGroup> <MSBuildCommunityTasksTargetFilePath>MSBuildCommunityTasks の Target ファイルの場所</MSBuildCommunityTasksTargetFilePath> </PropertyGroup> <ItemGroup> <OutputFiles Include="$(BinDirectoryPath)\*.dll"/> <OutputFiles Include="$(BinDirectoryPath)\*.xml"/> <OutputFiles Include="$(BinDirectoryPath)\*.config"/> <OutputFiles Include="$(BinDirectoryPath)\*.manifest"/> <OutputFiles Include="$(BinDirectoryPath)\*.exe"/> <OutputFiles Include="$(BinDirectoryPath)\config\*"/> <OutputFiles Include="$(BinDirectoryPath)\*.tt"/> <OutputFiles Include="$(BinDirectoryPath)\*.tpl"/> </ItemGroup> <Import Project="$(MSBuildCommunityTasksTargetFilePath)"/> <Target Name="BuildAll"> <!--作業フォルダ削除--> <RemoveDir Directories="$(WorkingDirectoryPath)" /> <!--リポジトリからコードとアセンブリをチェックアウト--> <SvnCheckout RepositoryPath="$(SourceRepositoryUrl)" LocalPath="$(WorkingDirectoryPath)"/> <SvnCheckout RepositoryPath="$(BinRepositoryUrl)" LocalPath="$(BinDirectoryPath)"/> <!--古いアセンブリを削除--> <SvnClient Command="delete" Targets="@(OutputFiles)"/> <SvnCommit Targets="$(BinDirectoryPath)" Message="古いアセンブリを削除。"/> <!--ビルド実行--> <MSBuild Projects="$(SolutionFilePath)" Properties="Configuration=Release;Platform=Any CPU;"/> <!--アセンブリをコミット--> <SvnClient Command="add" Targets="@(OutputFiles)"/> <SvnCommit Targets="$(BinDirectoryPath)" Message="新しいアセンブリを追加。"/> </Target> </Project>
ビルドするプロジェクトを増やすときは、既にある環境定義用ビルドファイルをコピーして、作業ディレクトリやリポジトリURLを書き変えればいい。
これでビルドファイルの保守がだいぶ楽になるな。もっと早くやればよかった。
*1:Visual Studio のプロジェクトのことじゃないよ!