如何同步EXE / DLL文件的SVN修订版本和版本资源?

13

假设我有一个构建 exe 或 dll 文件的 C++ 项目。该项目已经提交到 SVN 存储库中。我希望自动将 SVN 中的版本号与嵌入在我的 exe/dll 文件中的版本信息同步,即版本号应该类似于 $major.$minor.$svn_revision
有什么想法可以实现这个功能吗?是否有现成的解决方案可用?

4个回答

13
如果你安装了TortoiseSVN,那么它会自带一个程序SubWCRev
如果你的文件中有这个值:
$WCREV$

如果你执行类似于这样的操作,它将被替换为最高提交的修订号:

SubWCRev .\ yourfile.txt.template yourfile.txt

这将从yourfile.txt.template复制,进行替换,然后写入yourfile.txt

请注意,还有很多其他的宏可以使用,如果您执行SubWCRev而没有任何参数,则会在控制台上列出所有可用的宏。


5
SubWCRev也可单独使用,供不想使用TortoiseSVN的用户下载:http://sourceforge.net/project/showfiles.php?group_id=138498&package_id=281312 - Stefan
这就是我今天的事实 :) - Jim T
1
看起来单独可用的 SubWCRev 已经静态编译了,所以你只需要 exe 文件,而不需要一堆 TortoiseSVN DLLs。 - Craig McQueen
嗨,这不适用于资源文件。不知何故,它可以替换手写的.h文件中的$WCREV$字符串,但无法替换.rc文件。我创建了一个包含版本信息的资源文件version.template。我将其提供给subwcrev以生成实际的.rc文件,但是$WCREV$字符串仍然保持不变。有人有想法吗? - fgungor
无论如何,我解决了它。我从.rc文件中包含了我的自定义.h文件,一切都按预期工作。 - fgungor

4

Program.X的答案非常好。但是我想补充一点,如果在提交更改之前构建可执行文件,则修订版本将比运行代码的实际修订版本号少1。为了减轻这种情况,您可以设置版本为

"2.0.$WCREV$.$WCMODS?1:0$"

如果有本地修改,这将在结尾处添加1,否则添加0。因此,如果您稍后查看可执行文件并看到2.0.54.1,则知道它实际上可能是修订版55。

WCREV 中可用关键字的更多信息在此处提供:http://tortoisesvn.net/docs/release/TortoiseSVN_en/tsvn-subwcrev-keywords.html。 - Tom Hamming
好主意。我已经注意到了,看起来这是一个很好的解决方法来标记这个问题。 - Program.X
1
我喜欢这个,因为你可以看到版本是真正的SVN内容的1:1构建还是修改后的构建。 - Stiefel

3
这是非常有帮助的,谢谢。如果对任何人有帮助,我已经将其改进为Visual Studio 2008。
1/ 在每个项目中创建了一个/Build文件夹。
2/ 将AssemblyInfo.cs复制到Build文件夹中并将其命名为AssemblyInfo.cs.txt,并将生成操作设置为“无”。
3/ 编辑AssemblyInfo.cs.txt以获得以下版本属性:
[assembly: AssemblyVersion("2.0.0.$WCREV$")]
[assembly: AssemblyFileVersion("2.0.0.$WCREV$")]

4/ 将以下内容添加到预生成事件中:

SubWCRev $(SolutionDir) $(ProjectDir)\Build\AssemblyInfo.cs.txt $(ProjectDir)\Properties\AssemblyInfo.cs

这在每次编译时都有效。
我正在使用VisualSVN/TortoiseSVN和VisualSVN Server与Visual Studio 2008。
更新:
我的同事刚刚更新了他的工作副本,AssemblyInfo.cs发生了冲突。这似乎很明显。我使用VisualSVN将其从SVN中排除以解决此问题。

3
您可能想了解Subversion PropertiesSubversion Keywords。它们不能解决资源问题,因为它们始终包含该可恶的$KeywordName: ...$部分。自定义属性提供了一种很好的方法,可以在批处理文件等中提供元数据。
无论如何,几年前我寻找了解决资源问题的方法,但没有找到。所以,我们创建了自己的解决方案。我们更改了RC文件以包含在构建过程中生成的头文件。RC依赖于头文件,头文件具有自定义构建规则,调用批处理文件生成头文件。以下代码片段将从svn info的输出中提取当前修订版。
SET rootdir=%1
SET svnrev=0
PUSHD "%rootdir%"
FOR /F "tokens=1-4 delims=: " %%I IN ('svn info') DO (
    IF /I {%%I}=={rev} SET svnrev=%%L
)
(ECHO./*
 ECHO. * version-stamp.h - repository version information
 ECHO. */
 ECHO.#ifndef VERSION_STAMP_H
 ECHO.#define VERSION_STAMP_H
 ECHO.#define REPOSITORY_VERSION %svnrev%
 ECHO.#endif) > include\version-stamp.h
POPD

然后我们创建了一个特定组件版本标记头文件,名为component-info.h,大致如下:
#ifndef component_info_h
#define component_info_h
#include "product-info.h"
#include "version-stamp.h"

#define VERS_MAJOR 1
#define VERS_MINOR 2
#define VERS_PATCH 3
#define VERS_BUILD REPOSITORY_VERSION

#define MY_COMPONENT_NAME "TPS Report Generator"    
#define MY_VERSION_NUMBER VERS_MAJOR,VERS_MINOR,VERS_PATCH,VERS_BUILD
#define MY_VERSION_STRING VERSION_STRING(VERS_MAJOR,VERS_MINOR,VERS_PATCH,VERS_BUILD)

#endif

最后,我们有一个产品线版本文件,它定义了名为product-info.h的产品信息。
#ifndef product_info_h
#define product_info_h

#define PROD_VERS_MAJOR 0
#define PROD_VERS_MINOR 1
#define PROD_VERS_PATCH 0
#define PROD_VERS_BUILD 0

#define VSTR1(s) #s
#define VSTR(s) VSTR1(s)
#define VERSION_STRING(a,b,c,d) VSTR(a) "." VSTR(b) "." VSTR(c) "." VSTR(d) "\0"

#define MY_COMPANY_NAME         "IniTech\0"
#define MY_COPYRIGHT            "Copyright ©2009 " MY_COMPANY_NAME
#define MY_PRODUCT_NAME         "\0"
#define MY_PRODUCT_VERSION_NUM  PROD_VERS_MAJOR,PROD_VERS_MINOR,PROD_VERS_PATCH,PROD_VERS_BUILD
#define MY_PRODUCT_VERSION_STR  VERSION_STRING(PROD_VERS_MAJOR,PROD_VERS_MINOR,PROD_VERS_PATCH,PROD_VERS_BUILD)
#endif

您的资源文件应包括component-info.h,并在适当的位置使用各种定义(例如FILEVERSION MY_VERSION_NUMBER)。这种结构为我们提供了很多灵活性和整个版本标记过程的可追溯性。它从批处理文件中的简单块发展成为这种多级怪物,但在过去几年中它一直非常有效。
我认为很难相信还没有人找到更好的方法来解决这个问题。再说了,我已经有好几年没有研究过了。我会假设您可以添加一个自定义的.rules文件,定义一个处理此问题的自定义工具。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接