每次新版本build时,让软件的版本号自增

实现该目的,需要

  • 每次编译前,从svn获取当前版本库的版本号,并写入资源文件
  • 编译完成后,打安装包时,读取版本信息

需要注意两点:

1,svn的工具可获取版本号并更新到项目文件

如果提供了源文件和目的文件,SubWCRev 会复制源文件到目标文件,执行如下所属的关键字替换:

表 5.2. 列出可用的命令行开关

关键字 描述
$WCREV$ 用工作副本中最高的提交版本来替换
$WCDATE$ 用最高提交版本的日期/时间替换。默认使用国际化格式:yyyy-mm-dd hh:mm:ss。作为选择,你可以指定 strftime() 使用自定义格式,例如:$WCDATE=%a %b %d %I:%M:%S %p$。格式字符的列表参见 在线引用
$WCNOW$ Replaced with the current system date/time. This can be used to indicate the build time. Time formatting can be used as described for $WCDATE$.
$WCRANGE$ 在工作目录用更新版本范围替换。如果工作目录处于一致的状态,它是一个单一版本。如果工作目录包含混合版本,或者是过时,或者是故意更新到版本,那么这个范围会用象100:200这样的格式来显示。
$WCMIXED$ 当有混合版本时用 TText 替换 $WCMIXED?TText:FText$,否则用 FText 替换。
$WCMODS$ 若本地存在修改,就用 TText 替换 $WCMODS?TText:FText$,否则用 FText 替换。
$WCURL$ 用传递给SubWCRev的工作目录的版本库地址替换。
$WCINSVN$ $WCINSVN?TText:FText$ is replaced with TText if the entry is versioned, or FText if not.
$WCNEEDSLOCK$ $WCNEEDSLOCK?TText:FText$ is replaced with TText if the entry has the svn:needs-lock property set, or FText if not.
$WCISLOCKED$ $WCISLOCKED?TText:FText$ is replaced with TText if the entry is locked, or FText if not.
$WCLOCKDATE$ Replaced with the lock date. Time formatting can be used as described for $WCDATE$.
$WCLOCKOWNER$ Replaced with the name of the lock owner.
$WCLOCKCOMMENT$ Replaced with the comment of the lock.

下面的例子显示了模版文件中的关键字是如何在输出文件中被替换的。

// Test file for SubWCRev: testfile.tmpl

char *Revision = "$WCREV$";
char *Modified = "$WCMODS?Modified:Not modified$";
char *Date     = "$WCDATE$";
char *Range    = "$WCRANGE$";
char *Mixed    = "$WCMIXED?Mixed revision WC:Not mixed$";
char *URL      = "$WCURL$";

#if $WCMODS?1:0$
#error Source is modified
#endif

// End of file

After running SubWCRev.exe path\to\workingcopy testfile.tmpl testfile.txt, the output file testfile.txt would looks like this:

// Test file for SubWCRev: testfile.txt

char *Revision = "3701";
char *Modified = "Modified";
char *Date     = "2005/06/15 11:15:12";
char *Range    = "3699:3701";
char *Mixed    = "Mixed revision WC";
char *URL      = "http://project.domain.org/svn/trunk/src";

#if 1
#error Source is modified
#endif

// End of file

 

SubWCRev.exe从命令行或脚本中运行,使用命令行参数控制。

SubWCRev WorkingCopyPath [SrcVersionFile DstVersionFile] [-nmdfe]

WorkingCopyPath是要检查的工作副本路径,你可以只对工作副本使用SubWCRev,而不是直接对版本库,这个路径可以是绝对路径,也可以是工作目录的相对路径。

如果你想让SubWCRev执行关键字替换,象版本库版本,地址等字段保存到文本文件,就需要提供一个模版文件SrcVersionFile,输出文件DstVersionFile就是模版替换之后的版本。

有几个开关影响 SubWCRev工作。如果使用多个,必须用单个组指定,例如要用-nm,不能用-n -m

表 5.1. 列出可用的命令行开关

切换 描述
-n If this switch is given, SubWCRev will exit with ERRORLEVEL 7 if the working copy contains local modifications. This may be used to prevent building with uncommitted changes present.
-m If this switch is given, SubWCRev will exit with ERRORLEVEL 8 if the working copy contains mixed revisions. This may be used to prevent building with a partially updated working copy.
-d If this switch is given, SubWCRev will exit with ERRORLEVEL 9 if the destination file already exists.
-f 如果给出这个开关,SubWCRev 就会包含文件夹的最后修改版本。默认行为是取得版本号时只考虑文件。
-e If this switch is given, SubWCRev will examine directories which are included with svn:externals, but only if they are from the same repository. The default behaviour is to ignore externals.
-x If this switch is given, SubWCRev will output the revision numbers in HEX.
-X If this switch is given, SubWCRev will output the revision numbers in HEX, with '0X' prepended.

参考这个文档http://tortoisesvn.net/docs/nightly/TortoiseSVN_zh_CN/tsvn-subwcrev.html

2,每次编译版本前执行一次获取版本号操作

 

以 vc6 为例, 文件的版本信息保存在 rc 文件. 编译成 res 文件, 然后和其他 obj 一起 link. 现在的思路就是. 编辑 rc 文件, 将版本号比如 2.2.4.0 改成 2.2.4.$WCREV$, 在每次 link 之前, 先用 subwcrev.exe 处理 rc 文件, 进行宏替换. 然后调用 rc.exe 编译替换后的新文件. 生成 res 之后一起 link.

. 修改 rc 文件的 versioninfo 段成如下:
 #ifdef _AUTOVERSION
  FILEVERSION 2,2,4,$WCREV$
  PRODUCTVERSION 2,2,4,$WCREV$
 #else
  FILEVERSION 2,2,4,0
  PRODUCTVERSION 2,2,4,0
 #endif
 ...
 #ifdef _AUTOVERSION
    VALUE "FileVersion", "2, 2, 4, $WCREV$\0"
    VALUE "ProductVersion", "2, 2, 4, $WCREV$\0"
 #else
    VALUE "FileVersion", "2, 2, 4, 0\0"
    VALUE "ProductVersion", "2, 2, 4, 0\0"
 #endif           

其实也就是加上了条件编译. 默认情况下没有定义 _AUTOVERSION, 则使用原来的 fileversion, productversion. 如果定义了 _AUTOVERSION, 则使用新的版本信息.

. 在项目属性找到 pre-link 页. 在其中增加:
subwcrev\subwcrev.exe . myprogram.rc myprogram.rc_
rc.exe /l 0x804 /fo"\release\myprogram.res" /d "_AUTOVERSION" /d "_AFXDLL" "myprogram.rc_"

第一条命令处理 myprogram.rc , 生成 myprogram.rc_
第二条命令编译 myprogram.rc_ 为 myprogram.res, 注意它的路径. 这里是 release 版的默认路径.  原则就是这里生成的 res 替换原来的 res 文件.

按 f7, build. 现在版本信息已经刷新了. 每次向 svn 提交. 版本都会更新.

不过我们还可以更进一步. 将版本信息, 编译时间等写入到关于对话框中. 其实关键还是 pre-link.
. 创建一个文件 buildtime.cpp, 内容如下:
 const char*szBuildTime = "Build on $WCNOW$";
 const char*szFullVersion="MyProgram 2.2.4.$WCREV$$WCMODS?+:$$WCMIXED?#:$";

. 在关于对话框 OnInitDialog() 中加入:
 extern const char* szBuildTime;
 extern const char* szFullVersion;
 SetDlgItemText(IDC_BUILDTIME, szBuildTime);
 SetDlgItemText(IDC_VERSION, szFullVersion);

. 在 pre-link 再加上两条:
 subwcrev\subwcrev.exe . buildtime.cpp buildtime_.cpp
 cl /c /nologo /Fo\Release\buildtime.obj /MT buildTime_.cpp

原理和 rc 文件一样. 先替换, 后编译. 同样要保证生成的 buildtime.obj 覆盖原来的 buildtime.obj

大功告成.
不过有一点要注意. vc6 的资源编辑器在每次编辑资源之后都重新生成 rc 文件. 也就是说, 会删除我们对 rc 的修改. 还没有找到好的办法, 现在只能是每次编辑资源之后再手工添加一下条件编译的部分. 建议在项目进入 beta 之后再加上版本信息. 因为这个时候程序的资源一般都不会变动了.

另外, 虽然这里是以 vc6 为例, 但也可以应用到 vc2003, vc2005 等编译环境.

后记: 还可以考虑用程序自动修改. 找到 FILEVERSION, 将后面的版本替换成 FILEVERSION 2,2,4,$WCREV$, 然后再用 subwcrev 替换. 再用 rc 编译. 这样还不用定义 _AUTOVERSION 宏.


 

 

你可能感兴趣的:(每次新版本build时,让软件的版本号自增)