`
cppmule
  • 浏览: 447101 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类

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

    博客分类:
  • SCM
 
阅读更多



VC2005利用SVN的版本号,生成DLL和EXE文件的版本号

TortoiseSVN下有一个SubWCRev程序,可以获取任意个路径对应的SVN版本库的版本号。并替换到文件对应位置。

VC2005的资源文件可以控制生成的二进制文件版本号。

可以利用VC2005的生成前命令,调用SubWCRev来获取最新的SVN版本号并写入生成的二进制文件中。

程序也可以判断调用的DLL版本号是否比本身大。以控制不会调用不对应的动态库。可以使依赖多了一层运行时保证。

实现该目的,需要

  • 每次编译前,从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 withTTextif the entry is versioned, orFTextif not.
$WCNEEDSLOCK$ $WCNEEDSLOCK?TText:FText$is replaced withTTextif the entry has thesvn:needs-lockproperty set, orFTextif not.
$WCISLOCKED$ $WCISLOCKED?TText:FText$is replaced withTTextif the entry is locked, orFTextif 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 runningSubWCRev.exe path\to\workingcopy testfile.tmpl testfile.txt, the output filetestfile.txtwould 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 withERRORLEVEL 7if 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 withERRORLEVEL 8if 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 withERRORLEVEL 9if the destination file already exists.
-f 如果给出这个开关,SubWCRev 就会包含文件夹的最后修改版本。默认行为是取得版本号时只考虑文件。
-e If this switch is given, SubWCRev will examine directories which are included withsvn: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 宏

分享到:
评论

相关推荐

    vc 版本号自动增加

    VC自动更新版本号功能,可以在vc编译器里的pre build 里调用 计算检查和,可以在vc 编译器“生成后事件”调用。 注意,自动更新版本号时,如果增量编译,有时vc编译器并没有马上感应到有更新,未必将最新的rc文件...

    vue.js编译时给生成的文件增加版本号

    为了解决这个问题,我们可以编译时在生成的文件名中加入版本号,确保每次更新都能强制浏览器获取最新的资源。 Vue.js 编译时给生成的文件增加版本号主要通过Webpack的配置实现。以下是一种常见的做法: 1. **增加...

    js代码-4、动手实现一个版本号处理函数,维护不规则的版本号

    2. 次版本号:添加新功能但保持向后兼容时,次版本号会增加。 3. 修订号:修复错误或小改进时,修订号会增加。 在JavaScript中,我们可以创建一个名为`compareVersions`的函数,用于比较两个版本号。这个函数首先...

    Android代码-多渠道打包工具。

    Android渠道打包工具Gradle插件 渠道包数量很多(如100个以上),对打包速度有要求的建议使用新版极速打包工具 Packer-Ng,100个渠道包只需...支持自动修改versionName中的build版本号,实现版本号自动增长 gradle-pa

    GreenDao使用Demo

    - 当数据库结构需要更改时,如添加新字段或修改表结构,你需要增加数据库的版本号并提供升级方法。GreenDao会在升级时自动执行这些方法。 综上所述,"GreenDao使用Demo"虽然代码可能不够整洁,但它展示了如何在...

    roomTestDemo

    `entities`参数列出了所有数据库表对应的实体类,`version`是数据库版本号,每次数据库结构改变时应递增。 ### 5. 初始化和使用数据库 在应用程序中,我们需要创建`AppDatabase`的实例。由于它是单例模式,通常会...

    greendao3-jar.zip

    GreenDao提供了升级助手方法,开发者可以重写onUpgrade(),根据新旧版本号执行相应的迁移操作。 离线开发的环境意味着开发者需要提前下载好所有依赖库,包括GreenDao 3.0的JAR文件,然后在本地环境中使用。这可能...

    数据库操作

    记得替换x.x为最新版本号。然后同步项目,GreenDAO库就准备好了。 3. **实体类(Entity)** 在GreenDAO中,数据模型通过实体类表示。每个实体类对应数据库中的一个表,类的属性对应表的列。例如,创建一个`User`...

    redis安装与开发实例

    版本号 ``` 2. 连接Redis:使用Jedis实例化连接对象,如`Jedis jedis = new Jedis("localhost", 6379);`。 3. 数据操作:通过Jedis对象调用对应的方法实现数据的读写。例如,存储字符串: ```java jedis.set...

Global site tag (gtag.js) - Google Analytics