MsBuild是Visual Studio的建置系統,它是一個Xml格式的文件,
Visual Studio的專案檔其實就是使用MsBuild來寫的,
裡面描述了專案所包含的檔案有哪些,建置的設定等等資訊,
除了使用在Visual Studio的專案檔之外,我們也可以使用MsBuild來撰寫建置的流程,
再利用MsBuild寫好基本的範本之後,我們只要將需要分別設定的參數抽出來,
即可很快速地將我們的建置流程套用到不同的專案上面,
本篇文章將向大家介紹如何撰寫基本的MsBuild檔案
※基本框架
MsBuild的內容其實是由一個Project包含著多個Target所組合而成,
再依照參數的不同來決定將會執行那些Target,最基本的檔案格式如下
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="Build">
<Message Text="Hello Msbuild!" />
</Target>
</Project>
在專案檔中我們指定了預設執行的Target為Build,
在Build之中執行了顯示訊息的任務,在畫面上輸出Hello Msbuild!,
我們通常稱Message這項工作為Task,除了預設包含的Task之外也可以自己開發擴充,
更多的Task可以參考http://msdn.microsoft.com/zh-tw/library/7z253716.aspx
使用Visual Studio命令提示字元執行後可看到結果
執行語法: msbuild Sample01.csproj
如果今天我們希望可以按照順序執行多個任務,我們可以使用下面的寫法
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="Build">
<CallTarget Targets="Step 1"/>
<CallTarget Targets="Step 2"/>
<CallTarget Targets="Step 3"/>
</Target>
<Target Name="Step 1">
<Message Text="Step 1" />
</Target>
<Target Name="Step 2">
<Message Text="Step 2" />
</Target>
<Target Name="Step 3">
<Message Text="Step 3" />
</Target>
</Project>
執行結果
※ItemGroup和Item
我們在MsBuild中通常都會使用Item來指定專案建置所包含的項目,而ItemGroup代表Item的集合,
在ItemGroup之中,我們可以自己為Item取名,下面的例子中我將Item取名為ProjectFiles,
我用以下的語法來代表專案之中所有的cs檔,並可透過@(ItemName)來輸出內容
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ProjectFiles Include="C:\Users\kirkchen\Documents\GithubProject\CI-Sample\**\*.cs" />
</ItemGroup>
<Target Name="Build">
<Message Text="@(ProjectFiles)" />
</Target>
</Project>
執行結果
Item預設是使用分號做分隔,我們也可以透過@(ItemName,'Seperator')來指定分隔符號,
但如果我們將Item使用在串指令的時候,可使用@(ItemName->'Files:%(FullPath)','%0a'),例如
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ProjectFiles Include="C:\Users\kirkchen\Documents\GithubProject\CI-Sample\**\*.cs" />
</ItemGroup>
<Target Name="Build">
<Message Text="@(ProjectFiles->'Files:%(FullPath)','%0a')" />
</Target>
</Project>
執行結果 (%0a代表換行符號)
關於格式化輸出內容可以參考http://en.csharp-online.net/MSBuild%3A_By_Example%E2%80%94Formatting_Your_Output
※PropertyGroup和Property
在Msbuild中Project代表使用者定義的屬性和值,通常我們會用來存放可變更的參數
(例如: SourceMonitor執行路徑,檔案輸出位置等等)
並且可以使用$(PropertyName)來呼叫,請參考以下範例
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<SimianPath>"C:\Program Files (x86)\Simian\bin\simian-2.3.33.exe"</SimianPath>
</PropertyGroup>
<Target Name="Build">
<Message Text="$(SimianPath)" />
</Target>
</Project>
執行結果
※執行Task
在Target中的每一個執行動作,我們都稱他為Task (例如Message),
除了MsBuild本身支援的Task之外,我們也可以引用ThirdParty開發的Task,
例如我在之前掃描StyleCop時所寫的MsBuild檔案就是使用StyleCop所提供的Task,
透過Using Task來引用Dll,再執行所引用的Task,例如
<?xml version="1.0" encoding="utf-8"?>
<Project Defaulttargets="StyleCop" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<UsingTask AssemblyFile="$(MSBuildExtensionsPath)\..\StyleCop 4.7\StyleCop.dll" TaskName="StyleCopTask"/>
<ItemGroup>
<StyleCopFiles Include="C:\Users\kirkchen\Documents\GithubProject\CI-Sample\**\*.cs" Exclude="C:\Users\kirkchen\Documents\GithubProject\CI-Sample\**\*Test.cs" />
</ItemGroup>
<Target Name="StyleCop">
<StyleCopTask
ProjectFullPath="$(MSBuildProjectDirectory)"
SourceFiles="@(StyleCopFiles)"
ForceFullAnalysis="true"
TreatErrorsAsWarnings="true"
OutputFile="$(MSBuildStartupDirectory)\StyleCopReport.xml"
CacheResults="true" />
</Target>
</Project>
執行結果
※總結
透過本篇文章的介紹,我們已經可以初步了解MsBuild的撰寫方法,
接下來的文章中我將向大家介紹如何將建置流程的語法以MsBuild改寫,
以方便整合Jenkins時不需要設定太多的資料或建置的流程,
只要透過共用的MsBuild建置邏輯配合專案的獨立屬性設定,
就可以很快速地將CI每日建置套用到每個專案身上,
關於今天的分享,若有問題歡迎大家一起討論!