用MSBuild.... DailyBuild和软件开发流程的东东
看到CoolBug在研究有关NAnt的东东,感觉非常的有趣,也来聊聊这个问题,聊聊我喜欢的MSBuild,关于MSBuild 我想JJX比我更有发言权,很早的时候他的WebLog就有记载MSBuild
给我印象最深刻和让我觉得最有用的文章是Overview of MSBuild, Part 3: What Is the Limit to Extensibility? 很早时我们会因为一个人喜欢一个城市,因为喜欢某种黑客风格而喜欢一种技术,MSBuild的扩展性让我更喜欢它,有时我想这是一个工作流的引擎,是一个只要你愿意就可以将功能往上挂的框架,是一个非常Open和具有灵性的东东
CoolBug的研究也许源于这篇文章
Using Open Source .NET Tools for Sophisticated Builds - By Aaron Junod
我想每个项目都会建立一个软件开发的Process,而且很多时候我认为一个好的开发流程非常非常的重要,非常有讽刺的是以前我在奔步(一家立志过CMM4 ,CMM5的软件公司)的时候,一直感觉软件开发流程、文档和开发之间的重叠,因为太多的文档、太多的流程和太紧的项目交付时间,所以很容易失去重心,特别是开发人员,最后发现他们每天要做许多许多的工作,而且没有明确的Process的感觉,但每个人对Process的概念都非常的明确,当然这没有什么不好,唯一的问题,是一个执行和实施的效果问题,我记得那时候我们的项目交付时间往往总是被拖后。
成长总是比较烦恼和让人变得世俗起来,之后的项目流程也是如此,项目或产品的流程倾向于一种彻底的实用主义和程序化。希望这个流程能根据不同的项目组很快的搭建和实施,并取得不错的效果,制定的流程往往不仅为了这个项目而且还为了可以向其他的项目组进行复制;制定的开发流程也试着加入一些新的特性,比如XP的单元测试、XP开发中的交付计划,非常传统的Code Review等等。
总之,定义什么是一个我们需要的开发流程,我总结了下面几点:
1. 容易理解、容易使用、容易实施、很快可以收到实效
2. 数字特性,流程的许多地方是数量化的,可以进行查询、评估、检查、追溯、对比和反馈。
3. 灵活和可以变化的,流程中有永远不变的东西,并具有复制性;也有许多可以针对不同项目组、不同文化、不同产品要求进行变化的模块和特性
4. 个性化。对于一个项目,一个产品组来说,这种流程成为整个产品组或开发组比较个性化的一种共识,开始的时候也许难以适应,但之后你会发现它成为建造整个项目组开发文化的摇篮
5. 学习型。对于开发组和流程中的每个人对于这个流程都有自己的看法和认识,也许不是所有的人都一样,但是有一点非常明显的特性:每个人都知道这个流程不是完美和存在不足,但没有人攻击和挑战它,所有的建议和改变都希望是改进这个流程的不足或是带着通过改变使得这个流程更加完美的意愿来行动的
还好是WebLog,即使偏离了主题还可以继续,继续来讲讲如何用MSBuild 来实现软件开发流程中的DailyBuild 的过程。有关编译有几个不错的选择:NAnt、BuildIt、MSBuild当然还有批处理和其他的一些选择。我来之前,这个项目组是根据Team Development with Visual Studio .NET and Visual SourceSafe中的描述,使用BuildIt作为编译工具,BuildIt也挺好,但是扩展性比较差一些。NAnt应该是一个不错的选项,不过出于喜好,很容易的想到MSBuild,而且花了点时间,找到了一个for FX1.1的版本,这也就意味着不用等到VS2005,我们也不用按照FX2.0了J
好了简单的说一下我们要实现的一个DailyBuild的流程
1. 每天从Source Server(SS)上面获得所有的代码
2. 编译Visual Studio 的Solution
3. 将编译的结果收集到一个临时的Binn目录
4. 切换到VSS发布目录
5. 删除旧的发布文件,将新的编辑结果发布上去并做一个标签
6. 将编译成功的源代码和二进制文件打包备份到网络的另一台机器的backup\yyyy-MMdd-mmss目录
7. 当然如果你愿意还可以让它发一封Email通知你编译成功或失败,失败了最好发个短信给我J
@echo off
SET VSS_SS_DIR=C:\Program Files\VSS\win32
SET MSBUILD_DIR=C:\myProject\DailyBuild\MSBuild
SET NETFRAMEWOR_DIR=%SYSTEMROOT%\Microsoft.NET\Framework\%FRAMEWORK_VERSION%;
SET PATH=%PATH%;%NETFRAMEWOR_DIR%;%VSS_SS_DIR%;%MSBUILD_DIR%
SET BUILD_WORK_DIR=.\BuildTempXX
SET BUILD_BIN_DIR=%BUILD_WORK_DIR%\BINN
SET PUBLIC_ASSEMBLY_DIR=%BUILD_WORK_DIR%\PublicAssembly
SET VSS_BIN_DIR=$/SourceCode/Build/Latest
SET VSS_LASTVERSION_DIR=$/Source/Project/XXXXX/LastVersion/binn
SET MSBILD_FILE=DailyBuild.proj
SET VSS_CODE_DIR=C:\WorkDir\DailyBuild\VSS
SET SSDIR=\\10.01.10.11\XXXXXXX
SET SSUSER=DailyBuiler
SET SSPWD= DailyBuiler
@echo on
@echo ==========****获得访问权限*******=========
rem 获得访问的权限,访问任意目录 请确认该用户一定可以访问不然会出错
net use \\10.01.10.11 xxxx /user:xxxxx
rem 开始从VSS上下载代码
@echo ========****获得源代码*******========
rem 删除之前的文件
rd /s /q %VSS_CODE_DIR%
md %VSS_CODE_DIR%
rd /s /q %BUILD_WORK_DIR%
MSBuild %MSBILD_FILE% /t:GetSourceCode
rem 增加错误处理
if errorlevel 1 goto ErrHandelMSBuild
md %BUILD_WORK_DIR%
Xcopy %VSS_CODE_DIR% %BUILD_WORK_DIR% /s /e
rem 开始编译项目
@echo =======****开始编译项目文件*******=========
MSBuild %MSBILD_FILE% /t:Solution
rem 增加错误处理
if errorlevel 1 goto ErrHandelMSBuild
rem 收集编译结果并发布到一个临时的Bin目录
MSBuild %MSBILD_FILE% /t:CopyToBin
rem 增加错误处理
if errorlevel 1 goto ErrHandelMSBuild
rem 发布编译结果到VSS上
@echo =======****发布编译结果*******=============
@echo off
rem 发布编译好的结果到Build目录,供大家使用
rem 切换到发布目录 $/code/build/latest
SS CP %VSS_BIN_DIR%
rem 设置当前路径
SS workfold %VSS_BIN_DIR% %BUILD_BIN_DIR%
rem 删除之前的文件
SS Destroy -i-y *.*
rem 加编译的结果到VSS
SS Add %BUILD_BIN_DIR%\*.* -B -D –i-y -C"DailyBuild Add"
rem 加Label
SS LABEL %VSS_BIN_DIR% -L"Last Vesion" -i-y -C"DailyBuilder LABEL"
rem 发布完成后进行整理和备份工作
@echo =======================****进行最后的整理和备份工作*******=================
MSBuild %MSBILD_FILE% /t:BackupFiles
rem 删除工作目录
rem rd /s /q %BUILD_WORK_DIR%
rem rd /s /q %VSS_CODE_DIR%
@echo =====**** DaildBuild OK!*******=====
MSBuild %MSBILD_FILE% /t:EMailReportToMe
:ErrHandelMSBuild
ECHO ErrorEvel=%ERRORLEVEL%
rem MSBuild编译出错,表明这次编译不成功,不作处理,要做只做删除目录的处理
MSBuild %MSBILD_FILE% /t:EMailErrorReportToMe
goto Close
:Close
rem rd /s /q %BUILD_WORK_DIR%
rd /s /q %VSS_CODE_DIR%
goto end
:end
@echo ===========****End*******=========
pause
很长,但非常的简单和实用,我使用了一些批处理,因为这样不用在整段的写MSBuild Task了J 有关MSBuild的使用我们可以不讲,因为JJX的文档足够清楚了,这里有非常关键的一点需要和你分享,这不是MSBuild,是VSS的技巧,这是追求完美的人一定需要的
这个问题在发布的时候,当你的编译都通过了,要发布到VSS目录里的时候,会遇到一个版本覆盖的问题。
VSS 无论Check in还是删除原来的版本都有一个非常有趣的功能,提示不厌其烦的提示你是否同意,SS给也给一个非常无聊的参数-I 意思是忽略,但比较郁闷的是忽略的意思是给系统一个No的回答,那意味着什么?当系统问你是否要删除或覆盖旧的版本时它给了一个No的回答,还好还好,有微软有热情的微软工程师和Google,我们找到了这个技巧,默认它会不厌其烦的给提示一个Yes的回答,当然这是我们想要的
具体你可以查看bat文件和这个链接---VSS的Developer Support Engineer就是牛!
所有MSBuild %MSBILD_FILE% /t:XXXX的地方,都是写了自定义的Task来实现这个就不细说了。
MSBuild的另外一个好处,就是我上面讲的无限扩展的功能,很快很快我想你可以用MSBuild+NUnit完成一个BVT 的功能。当然如果你觉得Aaron Junod讲的也对,你还可以使用MSBuild+NDoc来完成一个自动文档化的功能,显然我喜欢BVT胜过NDoc,道路很简单,我觉得BVT比NDoc对我们的项目或开发更有用。
编程快乐