windows
原理
在vc编译前获取svn所在目录,获取目录的版本号,将版本号写入头文件resource.h, 在工程的资源文件中引用该版本号。
优点:每次版本发布时无需修改任何代码,可防止版本号被人为修改,引起混淆;写一个版本查看工具,可遍历项目所有可执行文件和动态库,获取其版本号。
缺点:工程第一次配置稍复杂,每次发布时需要先提交svn再编译,以获取最新的svn版本号。
方法步骤
准备
在svn根目录中保存批处理文件generateversion.bat和version.template。
generateversion.bat:搜索注册表,获取svn所在目录,获取svn工程目录的版本号,将版本号写入头文件。
generateversion.bat命令格式为:generateversion.bat [工程所在目录] [模板文件] [待生成的版本头文件]
generateversion.bat文件内容:
@ECHO ON
SETLOCALENABLEEXTENSIONS
REM InitializeConstants
SETTSVN_INFO_FILE=./TSVN_INFO.tmp
REM Initialize scriptarguments
SET workDir=%1
SET template=%2
SET target=%3
REM Goto main entry
GOTO MAIN
::=============================
::-----------------------------
::** Main entry
:MAIN
pushd %workDir%
SET workDir=./
REM 检查参数
IF%workDir%=="" GOTO ARGUMENT_ERROR
IF%template%=="" GOTO ARGUMENT_ERROR
IF%target%=="" GOTO ARGUMENT_ERROR
REM 查询注册表
reg queryHKLM\SOFTWARE\TortoiseSVN /v Directory > %TSVN_INFO_FILE% 2>NUL
REM 查找 TSVN 路径
FOR /F"tokens=*" %%i IN (%TSVN_INFO_FILE%) DO (
ECHO %%i | find "Directory" >NUL
IF %ERRORLEVEL% == 0 (
ECHO %%i > %TSVN_INFO_FILE%
)
)
SET /P TSVN_PATH=< %TSVN_INFO_FILE%
::路径偏移在23
SETTSVN_PATH=%TSVN_PATH:~23,-1%
REM 调用 TSVN 替换模板
IF NOT %ERRORLEVEL%== 0 GOTO UNKNOW_ERROR
"%TSVN_PATH%bin/SubWCRev.exe"%workDir% %template% %target% >NUL
IF NOT %ERRORLEVEL%== 0 GOTO UNKNOW_ERROR
GOTO SUCESSED
::=============================
::-----------------------------
::** Error handlers
:ARGUMENT_ERROR
ECHO 传入的参数无效。
GOTO FAIL
:NOT_FOUND_TSVN
ECHO 查询TortoiseSVN 的安装信息失败。
GOTO FAIL
:UNKNOW_ERROR
ECHO 生成程序集信息出现未知错误。
:FAIL
::=============================
::-----------------------------
::** Program exit
:FAIL
DEL /Q %TSVN_INFO_FILE% 2>NUL
ECHO 生成程序集信息失败。
popd
EXIT 1
:SUCESSED
DEL /Q %TSVN_INFO_FILE% 2>NUL
ECHO 生成程序集信息成功。
popd
EXIT 0
version.template:头文件模板。
version.template文件内容:
#defineVERSION_MAJOR 0
#defineVERSION_MINOR 0
#defineVERSION_REVISION 1
#defineVERSION_BUILD $WCREV$
#define NUM3STR(a,b,c) #a "." #b "."#c
#defineNUM4STR(a,b,c,d) #a "."#b "." #c "." #d
#defineVERSIONSTR(a,b,c) NUM3STR(a,b,c)
#defineVERSIONBUILDSTR(a,b,c,d) NUM4STR(a,b,c,d)
#defineFILE_VERSION_STR VERSIONBUILDSTR(VERSION_MAJOR,VERSION_MINOR,VERSION_REVISION,VERSION_BUILD)
#definePRODUCT_VERSION_STR VERSIONSTR(VERSION_MAJOR,VERSION_MINOR,VERSION_REVISION)
#define SRC_TIME"$WCDATE$"
#define BUILDING_TIME"$WCNOW$"
模板宏定义
VERSION_MAJOR |
主版本 |
VERSION_MINOR |
次版本 |
VERSION_REVISION |
修订版本 |
VERSION_BUILD |
编译版本 |
NUM3STR |
三个数字的版本(主版本.次版本.修订版本) |
NUM4STR |
四个数字的版本(主版本.次版本.修订版本.编译版本) |
VERSIONSTR |
大版本号 |
VERSIONBUILDSTR |
详细版本号 |
FILE_VERSION_STR |
文件版本串 |
PRODUCT_VERSION_STR |
产品版本串 |
SRC_TIME |
代码时间 |
BUILDING_TIME |
编译时间 |
步骤
1. 工程中添加资源文件,假定名字为ver.rc,再选择添加资源【Version】,用UE编辑ver.rc
找到如下代码:
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,0,0,1
PRODUCTVERSION 1,0,0,1
FILEFLAGSMASK 0x17L
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS0x4L
FILETYPE0x1L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "080404b0"
BEGIN
VALUE "FileDescription", "sys_tran 应用程序"
VALUE"FileVersion", "1, 0, 0, 1"
VALUE "InternalName", "sys_tran"
VALUE "LegalCopyright", "Copyright (C) 2013"
VALUE "OriginalFilename", "sys_tran.exe"
VALUE "ProductName", "sys_tran 应用程序"
VALUE"ProductVersion", "1, 0, 0, 1"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x804, 1200
END
END
2. 修改版本文件
以上标记为黄色背景色的为版本信息,需要修改为:
FILEVERSION VERSION_MAJOR,VERSION_MINOR, VERSION_REVISION, VERSION_BUILD
PRODUCTVERSION VERSION_MAJOR, VERSION_MINOR,VERSION_REVISION, VERSION_BUILD
VALUE "FileVersion",FILE_VERSION_STR
VALUE "ProductVersion",PRODUCT_VERSION_STR
3. 在vc工程的预生成事件中添加批处理命令
如某个工程的命令:
"$(ZH9000_HOME)\src\generateversion.bat"$(ProjectDir)..\ $(ZH9000_HOME)\src\version.template $(ProjectDir)\resource.h
注意事项
a) 大版本号改变时手动在模板中修改。
b) 批处理第一个参数【工程所在目录】为工程目录,它可能是svn下某个子目录,该目录之外的svn版本改变不会改变该【工程所在目录】的版本号,如项目包含一个dll,一个exe,当dll版本号改变时,exe版本号不会引起改变,同样,如果工程引用了头文件,甚至是源文件,该文件不在工程目录中,当该文件发生改变时,不会引起工程版本号的改变。当然,如果工程所在目录指定为svn根目录,那么获取的svn则永远是最大版本号。
c) 静态链接库代码(lib)不会参与版本发布,可将静态链接库编译库放在svn中参与版本控制。
d) 如果多个工程文件在同一个目录内,那么需要用不同名字区分其资源文件,并且版本头文件也需要用不同名字区分,在资源文件中修改#include "resource.h"相应的代码。
linux
原理
linux下采用文件名跟随版本号的方式表示其版本号。在makefile中在编译时从version.template中获得大版本号,然后从svn中获得svn版本号,在makefile中将版本信息输出到变量中,并合并到输出文件后。
方法步骤
准备
准备template.version,内容参见windows章节。
准备脚本makev.py,作用:获得发布版本信息,以.x.x.x.x格式输出。
代码中标黄的部分为获取大版本信息,可根据实际项目修改version.template路径
#! /usr/bin/python
# -*- coding:utf-8-*-
import os, re, sys,os.path,subprocess
def getBigVer():
zh9000_home=os.getenv("ZH9000_HOME")
vt_path=zh9000_home+"/src/version.template"
vt = open(vt_path)
major = re.split(" *", vt.readline())[2]
minor = re.split(" *", vt.readline())[2]
revision = re.split(" *",vt.readline())[2]
vt.close()
return major +"."+ minor +"." + revision
defgetSvnDirFromMakefile():
svn_path= "."
if(len(sys.argv) > 2):
svn_path = sys.argv[2]
return svn_path
def getSvnVer():
svndir=getSvnDirFromMakefile()
if len(svndir) == 0:
return ""
#print "svndir="+ svndir
cmd_str = "svn info %s | grep Revision| awk \'{print $2}\'"%svndir
#print cmd_str
psvn = os.popen(cmd_str)
pout = psvn.readline()
if pout:
psvn.close()
return str(pout)
psvn.close()
cmd_str = "svn info %s | grep 修改的版本 | awk\'{print $2}\'"%svndir
psvn = os.popen(cmd_str)
pout = psvn.readline()
if pout:
psvn.close()
return str(pout)
psvn.close()
return "1"
svnVer = getSvnVer()
#ver_makefile =sys.argv[2]
#print"ver_makefile:" + ver_makefile
print "." +getBigVer() + "." + svnVer.replace('\r', ' ').replace('\n', ' ')
步骤
在makefile中定义获得svn版本的路径VER_DIR,如VER_DIR=../,默认为.,即当前目录。
定义版本信息:VER:=$(shell $(ZH9000_HOME)/src/Build/gnu/makev.py $0 $(VER_DIR)),语句中,makev.py为准备工作中的makev.py文件,$0为makefile路径,VER_DIR为svn版本信息相关路径。
输出文件proc_name=xxx$(VER),之后引用proc_name,动态库同理。
编译时执行make命令编译
注意事项
a) 同windows版本发布注意事项a),b),c)
b) linux服务器中代码必须在svn版本控制范围中,如果不在版本控制范围内,或者未安装svn,默认svn号为1。
建议
将获取版本信息等代码抽取到公共makefile中,工程makefile中只定义VER_DIR,然后包含公用makefile,统一管理公共代码,方便维护。