1 、 MSBuild
1.1 、概述
MSBuild ( Microsoft Build Engine )是 Microsoft 的新的生成平台,通过 MSBuild 可以创建和编辑可扩展的生成解决方案。从 Visual Studio 2005 之后, CLR 项目的生成工作就转由 MSBuild 完成,大家比较一下 Visual Studio 2005/2008 下 C# 工程和 VC 工程就会发现其中的不同。
MSBuild 可以认为是 makefile 的扩展,采用 XML 格式的项目文件描述生成过程中的任务序列,有能力的用户可以自行调整生成过程。
1.1.1、 MSBuild 平台包括:
1.1.1.1、 执行引擎: MSBuild.exe 和 Microsoft.Build.Engine.dll ,用于完成生成工作的引擎。
1.1.1.2、 MSBuild 项目文件的规范。
1.1.1.3、 MSBuild 的基本任务( Task )及其扩展机制。 Microsoft.Build.Framework 、 Microsoft.Build.Task 等一系列 Assembly 。
1.1.2、 在 MSBuild 平台可以完成的工作
1.1.2.1 、编写 MSBuild 项目文件,能够自行定义生成过程中每一个活动的细节。
1.1.2.2 、根据需要可以编写扩展任务。通过扩展任务可以完成计算机平台下几乎所有的工作,为此 MSBuild 相当灵活和强大。
MSBuild 出现之前, ANT/NANT 是比较流行的构造平台,简单的比较了一下,两者的能力几乎完全重叠,从扩展的角度来说 MSBuild 更容易被 CLR 平台下的开发人员所接受, ANT 之流应该无需考虑了。
1.2 、几个重要概念
在 MSBuild 平台下,生成过程是通过命令行启动控制台程序 MSBuild.exe 解析项目文件并且逐一执行项目文件中定义的任务完成的。 MSBuild 项目文件是一个基于 XML 格式的纯文本文件,规范中定义的几个概念对于理解其运作非常重要。
1.2.1 、属性
属性是可用于配置生成的键 / 值对。属性可用于将值传递给任务、按条件进行计算以及存储将在整个项目文件中引用的值。
在项目文件中表现为 <PropertyGroup> 元素下的子元素,元素名称即为属性名,可以在整个项目文件中使用 $(PropertyName) 引用。除了可以在项目文件中定义外,还可以通过命令行设置。例如:
<PropertyGroup>
<BuildDir>Build</BuildDir>
</PropertyGroup>
为了便于理解,我们可以认为属性相当于字符串类型的全局变量。
1.2.2 、项
项表示对生成系统的输入,项通常都是成组出现,这些项根据其用户定义的集合名称被组合为项集合。这些项集合可以用作任务的参数,任务使用集合中包含的各个项执行生成过程的步骤。
在项目文件中表现为 <ItemGroup> 元素下的子元素,元素名称为项集合的名称,可以在整个项目文件中使用 @(ItemName) 引用项集合。例如:
<ItemGroup>
<Compile Include = "file1.cs"/>
<Compile Include = "file2.cs"/>
</ItemGroup>
项与集合乍一看非常雷同,两者的主要区别如下:
l 项总是成组出现并且使用,不存在只使用某一个项的情况,而属性可以单个使用,并且不存在同名却值不同的两个属性。
l 从语法结构上来看,属性就是简单的值名对;而项可以包含称之为“元数据”的子元素,并且项集合还能够通过元数据进行分组,便于使用的时候筛选。
l 属性可以通过命令行的形式动态添加,而项集合只能够在项目文件中定义,当然可以通过执行任务改变项集合中包含的成员(也就是项)。
通俗地讲属性是字符串类型变量;项是对象(具体来说就是实现ITaskItem 接口的对象实例),元数据是对象的特性(成员变量);项集合是集合类型的变量,项是集合中的成员。
1.2.3 、任务
任务是 MSBuild 用来执行原子声称曹操作的可执行代码单元。任务包含了两部分的概念:任务逻辑和执行任务。
1.2.3.1 、任务逻辑是 CLR 代码,准确的说就是实现了 Microsoft.Build.Framework.ITask 接口的 .NET 类。
MSBuild 自身提供了一些常用的任务,我们也可以通过实现 ITask 接口定义扩展任务。
1.2.3.2 、执行任务
在项目文件中执行任务之前,必须首先使用 UsingTask 元素将实现任务的程序集中的类型映射到任务名称。这样便于 MSBuild 引擎查找任务的执行逻辑了。
若要在 MSBuild 项目文件中执行任务,请创建一个具有任务的名称的元素,作为 <Target> 元素的子级。如果任务接受参数,它们将作为元素的属性传递。如果任务支持返回类型的参数,则通过在任务元素下声明 <Output> 子元素接收返回值。例如:
<Target Name="CopyFiles">
<Copy
SourceFiles="@(MySourceFiles)"
DestinationFolder="@(MyDestFolder)">
<Output
TaskParameter="CopiedFiles"
ItemName="SuccessfullyCopiedFiles"/>
</Copy>
</Target>
这段代码表示执行 Copy 任务,将 MySourcesFiles 项集合中定义的文件复制到 MyDestFolder 项集合中定义的目录下,成功执行复制的文件存放到 SuccessfullyCopiedFiles 项集合中。
通俗的讲,相当于外部函数,执行任务就是执行外部函数。
1.2.4 、目标
目标就是以特定顺序的任务集合,目标内的任务将依次序顺序执行。
在项目文件中目标表现为 <Target> 元素,其下包含一组 Task 子元素。例如:
<Target Name="Build">
<GenerateResource
Sources="alpha.resx; beta.txt"
<Output
TaskParameter="OutputResources"
ItemName="Resources"/>
</GenerateResource>
<Csc
Sources="hello.cs"
Resources="@(Resources)"
OutputAssembly="hello.exe"/>
</Target>
一个项目文件中可以定义多了目标,可以通过设定目标的 DependsOnTargets 属性来要求在执行一个目标前先执行其它多个目标。例如上面的事例可以重新定义为:
<Target Name="Resources">
<GenerateResource
Sources="alpha.resx; beta.txt"
<Output
TaskParameter="OutputResources"
ItemName="Resources"/>
</GenerateResource>
</Target>
<Target Name="Build" DependsOnTargets="Resources">
<Csc
Sources="hello.cs"
Resources="@(Resources)"
OutputAssembly="hello.exe"/>
</Target>
通俗的说目标就相当于子程序( Procedure ),它是项目文件内部,构造逻辑重用的单元。
1.2.5 、项目文件
一个项目文件定义了一次完整的构造,例如一个 CLR 项目的工程。
MSBuild 项目文件是一个根元素为 <Project> 的 XML 文档,其中包含了多个 <Targets> , 可以通过设置项目文件的 InitialTargets/DefaultTargets 属性来设定构造过程需要执行的目标,也可以通过命令行来设定构造过程需要执行的目标。例如:
msbuild <file name>.proj /t:Clean;Compile
2 、 Team Foundation Build
MSBuild 是一个比较强大并且易于扩展的平台,但是它的价值在于构造一个完整的项目而非一个组件。如果仅仅希望构造一个组件,那么根本不需要研究 MSBuild , Visual Studio 已经为我们代劳了一切,虽然有些地方还不尽如人意。另一方面如果要构造一个多人协同开发的完整项目单靠 MSBuild 显然是不能胜任的,还涉及到源代码管理、测试、发布和报告等一系列主题。还好有 Team Foundation ,其中包含的 Team Foundation Build 就是用来填补这部分鸿沟的。
2.1 、概述
Team Foundation 为团队开发提供了版本控制、工作项跟踪、单元测试等从工具到平台的一系列支持。 Team Foundation Build 是 Team Foundation Server 的一部分,对构造提供了扩展的支持。
使用 Team Foundation Build ,可以同步源代码、编译应用程序、运行关联的单元测试、执行代码分析、在文件服务器上发布生成,以及发布生成报告。生成结果数据将传播到仓库以生成历史记录报告。
2.1.1 、组成
2.1.1.1 、源代码管理。存储所有源代码的 Team Foujndation 版本控制服务器。
2.1.1.2 、 Team Foundation Build Web 服务。在应用程上运行的 Web 服务,接受来自客户端的请求并协调生成步骤地执行。
2.1.1.3 、生成服务, TFSBuildService.exe 。
可以部署在单独的计算机上,在一个构造环境中可以安装设置多台计算机分别安装生成服务,运行生成服务的计算机称之为生成代理。生成代理根据 Team Build Web 服务的说明运行生成步骤。
也可以通过调用命令行工具 TFSBuild.exe 完成生成动作。可
2.1.1.4 、客户端,与 Visual Studio 集成的 Team Explorer 。可以创建修改生成定义、查看生成报告和生成进度信息。
2.1.2 、相对于 MSBuild 扩展内容
Team Foundation Build 的核心就是生成服务和生成定义,简单的说就是生成服务解析生成定义,按其描述完成构造动作。生成定义是什么?它就是一个遵循 MSBuild 文档架构的项目文件。可以认为 Team Foundation Build 就是考虑到与 Team Foundation 的需要对 MSBuild 进行的扩展。
其主要扩展内容包括:
2.1.2.1 、为 MSBuild 提供了扩展任务( Microsoft.TeamFoundation.Build.Tasks ),以完成和 Team Foundation 协同的工作,例如从版本控制服务器中获取代码、设置标签等。
2.1.2.2 、预定义了一些可扩展的目标,相当于可重载的虚函数。重写这些目标以便于完成自定义任务。
2.1.2.3 、通过定义触发器能够自动启动构造过程,触发器有多种类型,比如定时或者代码库中发生变更。
2.1.2.4 、通过 Team Foundation Server 提供的测试平台,能够在构造过程中运行测试项目和进行代码覆盖率的检查,以达到自动测试的目的。
2.1.2.5 、已经包含了构造失败发邮件通知,构造成功生成报告的机制。并且在生成报告中能够反映代码集和任务的变更。
因此在 Team Foundation Server 的协助下, Team Foundation Build 是一个比较完善的自动构造平台。
2.2 、利用 Team Foundation Build 实现每日构造
如果没有特殊要求,利用和 Visual Studio 集成的 Team Explorer 这个可视化的工具就可以完成,非常容易。
2.2.1 、首先需要设置生成代理, Build à Manage Build Agents… 。
2.2.2 、创建生成定义, Build à New Build Definition… 。可以参考: http://msdn.microsoft.com/zh-cn/library/ms181286(VS.80).aspx
2.2.3 、如果想实现每日构造,只需要在生成定义中将触发器类型选择为“ Build every week on the following days ”,选择从星期一到星期日的全部天数,然后再指定一下构造时间(例如: 17 : 00 )即可。
设置完毕后,每天的 17 点, Team Foundation Build 就会依照生成定义中指定的内容自动执行构造动作同时会生成一份构造报告供我们查看。
以上主要是根据 MSDN 中 MSBuild 和 Team Foundation 等章节进行整理,试图通过个人理解来阐述一些基本概念,为开展自动构造活动进行一些基础准备。