每日编译的入门实践
(作者:Jackey,网址:www.kuihua.net)
1 引言:
有关每日编译(Daily-Build、Night-Build)的讨论在网上已经很多,但大多都是停留在形式上或纯粹是一种谈资,很少看到一些真正有用的、可操作的东西。不过,网上倒是有很多开源的每日编译系统,ANT、NANT等,感觉都是针对.net或java开发的,对常规的应用程序开发好像有点不是太适合,而且系统过于庞大,需要很多外围软件的支持。
鉴于此,本人利用BAT和Perl脚本实现了一个入门级的每日编译系统。
2 本文需要建立的工作环境:
2.1 系统运行环境:
l 开发环境:Visual C++ 6.0
l 打包环境:Install Shield 6.1
l 脚本环境:Active Perl 5.6.1
l 操作系统:Win2000/WinXP
l CVS环境:WinCVS(1.3.13.1)、CVSNT(2.0.4)
l CVS设置::pserver:jackey@server:D:/KHBuild
l CVS2CL:变更日志工具,是个Perl脚本,下载地址:http://www.red-bean.com/cvs2cl
l 环境变量:需要为Install Shield手工建立Path系统变量,其它工具会在安装时自动添加。
2.2 目录环境与例子工程设置:
l 测试工程在cvs中目录结构:
\TestProject\Source // 测试工程源代码目录
\TestProject\Install // 测试工程安装代码目录
l 每日编译目录环境设置:
D:\CVSBuild // 临时编译目录
D:\DailyBuild // 每日编译目录
\Product // 所有产品目录
\TestProject // 测试产品目录
\2004-9-1 // 2004.9.1的产品
\2004-9-2 // 2004.9.2的产品
\2004-9-3 // 2004.9.3的产品
\BuildLog // 所有产品的日志
\TestProject // 测试产品的日志
\ChangeLog.txt // 测试产品的代码变更日志
\2004-9-1 // 2004.9.1的编译日志
\2004-9-2 // 2004.9.2的编译日志
\2004-9-3 // 2004.9.3的编译日志
\sys.log // 系统日志
\cvs.log // cvs代码下载日志
\vc6.log // vc6代码编译日志
\install.log // 打包程序编译日志
\Script
\cvs2cl.pl // 产生ChangeLog的Perl脚本
\FilePath.pl // 修改Install Shield的绝对路径的Perl脚本
\LoadTest.bat // 用于Windows自动任务调用的批处理
\BuildTest.bat // 被LoadTest.bat调用的实际自动编译脚本
3 BuildTest.bat的实现思路:
l 参数说明:
1. 指定编译中间过程存放的盘符。 (如:D: )
2. 指定每日编译存放的盘符,可以是网络盘。 (如:E: )
3. 指定cvs所需要的代码仓库信息。
l 具体实现步骤:
1. 判断输入参数的合法性;
2. 得到当前日期,通常的格式为:2004-9-5
3. 设置环境变量,方便进一步的操作;
4. 进入脚本所在目录;
5. 删除当天编译过的目录,保证只留一份当天的产品;
6. 创建当天产品的存放目录;
7. 将当前的系统环境状态写入sys.log日志文件中;
8. 从cvsnt中下载TestProjet的源代码和安装代码;
9. 使用cvs2cl.pl为下载后的代码产生代码变更日志(ChangeLog.txt)
10. 使用FilePath.pl修改安装代码里的绝对路径;
11. 使用msdev.exe编译TestProject工程;
12. 使用isbuild.exe编译TestProject的安装代码;
13. 将编译后的安装程序拷贝到指定的每日编译目录;
14. 删除一些不需要的临时目录;
15. 编译结束。
l 为了实现每日编译的自动化,需要建立一个Windows系统任务,让它在每天午夜的时候自动调用LoadTest.bat,实现真正意义上的Daily-Build或Night-Build。
4 仅供参考的实现脚本:
4.1 LoadTest.bat实现参考:
BuildTest.bat D: D: jackey@server:D:/KHBuild
4.2 BuildTest.bat实现参考:
@echo off
REM ------- Check the input Param is validate! --------
if "%1"=="" goto :Usage
if "%2"=="" goto :Usage
if "%3"=="" goto :Usage
echo Starting daily-build for TestProject product...
date /t > date.inf
for /F "tokens=1* delims=, " %%I in (date.inf) do set DATE=%%I
del date.inf
set PROJECT=TestProject
set BUILD_PATH=%1\CVSBuild
set SCRIPT_PATH=%2\DailyBuild\Script
set PRODUCT_PATH=%2\DailyBuild\Product\TestProject\%DATE%
set LOG_PATH=%2\DailyBuild\BuildLog\TestProject\%DATE%
set CVSROOT=-d:pserver:%3
set CODE_PATH=%BUILD_PATH%\TestProject
set SYS_LOG=%LOG_PATH%\sys.log
set CVS_LOG=%LOG_PATH%\cvs.log
set VC6_LOG=%LOG_PATH%\vc6.log
set INSTALL_LOG=%LOG_PATH%\install.log
set CHANGE_LOG=%2\DailyBuild\BuildLog\TestProject\ChangeLog.txt
cd /d %SCRIPT_PATH%
rd /s /q %PRODUCT_PATH%
rd /s /q %LOG_PATH%
md %BUILD_PATH%
md %PRODUCT_PATH%
md %LOG_PATH%
time /t >> %SYS_LOG%
date /t >> %SYS_LOG%
echo 工程名称 = %PROJECT% >> %SYS_LOG%
echo 产品路径 = %PRODUCT_PATH% >> %SYS_LOG%
echo 编译路径 = %BUILD_PATH% >> %SYS_LOG%
echo 代码路径 = %CODE_PATH% >> %SYS_LOG%
echo 日志路径 = %LOG_PATH% >> %SYS_LOG%
echo CVS参数 = %CVSROOT% >> %SYS_LOG%
echo CVS日志 = %CVS_LOG% >> %SYS_LOG%
echo VC6日志 = %VC6_LOG% >> %SYS_LOG%
echo 系统日志 = %SYS_LOG% >> %SYS_LOG%
echo 安装日志 = %INSTALL_LOG% >> %SYS_LOG%
echo 更新日志 = %CHANGE_LOG% >> %SYS_LOG%
echo [...Checkout Source Code...] >> %CVS_LOG%
cvs %CVSROOT% checkout -d %BUILD_PATH%\Source TestProject\Source >> %CVS_LOG%
echo [...Checkout Install Code...] >> %CVS_LOG%
cvs %CVSROOT% checkout -d %BUILD_PATH%\Install TestProject\Install >> %CVS_LOG%
echo [...Building ChangeLog for this version...]
cd /d %CODE_PATH%
%SCRIPT_PATH%\cvs2cl.pl --hide-filenames -P -f ChangeLog.txt
copy /Y ChangeLog.txt %CHANGE_LOG%
del ChangeLog.txt
cd /d %SCRIPT_PATH%
echo [...Building TestProject...]
msdev %CODE_PATH%\Source\TestProject.dsw /MAKE "TestProject - Win32 Release" /REBUILD >> %VC6_LOG%
echo [...Building Installshield code...]
FilePath.pl %PROJECT% %CODE_PATH% %CODE_PATH%\Install\ >> %INSTALL_LOG%
isbuild -m"Default" -p"%CODE_PATH%\Install\TestProject.ipr" -b"%BUILD_PATH%\Test" -r >> %INSTALL_LOG%
echo [Copy Install files to daily-build Repository...]
xcopy /Y %BUILD_PATH%\Test\DiskIm~1\Disk1\*.* %PRODUCT_PATH%
echo [Now, delete the temporary build-path...]
rd /s /q %BUILD_PATH%
goto :EOF
REM ------- Print the usage for this .bat file --------
:Usage
echo ---------------------------------------------------------------------------------------------
echo +
echo + %0 [Temp disk volume] [Dest disk volume] [user@server:path]
echo +
echo + [ Example ] : %0 D: E: administrator@localhost:D:/KHBuild
echo + [Temp disk volume] : 指定编译中间过程存放的盘符。 (如:D: )
echo + [Desk disk volume] : 指定每日编译存放的盘符,可以是网络盘。(如:E: )
echo + [user@server:path] : 指定cvs所需要的代码仓库信息。
echo +
echo ---------------------------------------------------------------------------------------------
:EOF
4.3 FilePath.pl实现参考:
#!/user/bin/perl -w
my $search = "=.*$ARGV[0]"; # Search value
my $replace = "=$ARGV[1]"; # Replace value
my $dirname = "$ARGV[2]File Groups"; # Search directory
print "\r\n";
print "Search is \"$search\"\r\n";
print "Replace is \"$replace\"\r\n";
print "Directory is \"$dirname\"\r\n";
print "\r\n";
opendir DIR, $dirname or die "Cannot open $dirname: $!"; # Open directory
foreach my $filename (readdir DIR) # Enumerate directory file
{
next if $filename =~ /^\./; # Skip . and ..
next if $filename =~ /CVS/;
next if $filename =~ /\.fdf/;
$filename = "$dirname\\$filename"; # Append directory path
open(INFILE, "$filename") || die "cannot open $filename: $!";
open(OUTFILE, ">$filename"."_bak") || die "$!"; # Open and create file
print "[ Processing file is \"$filename\"... ]\r\n\r\n";
while( <INFILE> ) # Enumerate all lines
{
s/$search/$replace/g; # Search and replace in global
print $_; # Print the replace result
print OUTFILE $_; # Save in new file
}
close INFILE; # Close in_file
close OUTFILE; # Close out_file
rename $filename . "_bak", $filename; # Rename out_file to in_file
}
closedir DIR; # Close the directory
5 每日编译的应用探讨:
5.1 建立核心链条思想:
源代码管理工具 => Bug追踪工具 => 每日编译工具
WinCVS/CVSNT => Bugzilla => BAT和Perl脚本
5.2 如何运用这些工具:
l 必须建立源代码的版本控制系统,就是cvs,基本的代码提交原则:
1. 程序员尽量每天只在下班前提交一次;
2. 提交的代码必须是在自己的机器上是正常运行的;
3. 每次提交都必须用简短的话说明自己提交代码的功能描述。
l 建立错误追踪系统,用Bugzilla就很好,配置好邮件系统,使Bugzilla成为测试人员与开发人员沟通的桥梁。
l 用BAT和Perl脚本,以cvs中的源代码为核心实现简单的每日编译工具,将这个自己写的自动化工具放到一台专门的编译机器上,在每天的半夜开始自动下载代码,自动编译代码,自动打包安装程序,自动记录各种编译日志,自动将安装程序放置到一个固定的以日期为目录名的公共区。(用cvs2cl.pl得到程序员上传的代码更新日志,以便测试人员参考)
l 测试人员的第二天,应该到公共区取得头天的最新版本,并根据ChangeLog进行新版本的测试。并将测试中发现的Bug,通过Bugzilla反馈给程序员。程序员可以根据自己的情况,或公司的规定来决定修改这些Bug的时间。并将这些Bug的修改情况,在代码提交时,写入代码日志。
l 开发人员的第二天,应该到公共区查看编译日志,看看自己的模块是否正常编译,及时更正,看看自己的邮箱有没有Bug报告,及时修改。
l 管理人员的第二天,在综合项目需求与头天版本进度的基础上,可以判断产品的发展方向,如果有偏航或理解错误或有新需求时,可以根据当前情况及时调整。
l 这样,通过 cvs => bugzilla => daily-build,就能将程序员与测试员,进行互动,各施其责。减少沟通与人为的麻烦。对于管理层,也能做到心中有数:因为每天都有新版本,随时掌握产品的走向。。。等等。
5.3 本人写的相关工具的文档:
l WinCVS/CVSNT的简明手则:
http://blog.csdn.net/ycw/archive/2003/12/29/4183.aspx
http://blog.csdn.net/ycw/archive/2003/07/18/4184.aspx
http://blog.csdn.net/ycw/archive/2003/07/18/4185.aspx
http://blog.csdn.net/ycw/archive/2003/07/18/4186.aspx
l Bugzilla的安装实录:
http://blog.csdn.net/ycw/archive/2004/02/07/4187.aspx
http://blog.csdn.net/ycw/archive/2004/02/07/4188.aspx