【问题标题】:use svn revision number in application version在应用程序版本中使用 svn 修订号
【发布时间】:2012-08-21 14:36:06
【问题描述】:

在 VS2010 解决方案(不是 .NET)中,我希望将 svn 修订号作为应用程序版本的一部分。

我们目前不使用 makefile,仅使用 VS 解决方案/项目设置。

我想在编译时获取工作副本修订号,将其存储到一个变量中,以便稍后在代码中使用它来显示版本号。

到目前为止,我已成功使用svnversion 将最新版本的工作副本作为预建事件

"C:\Program Files\CollabNet\Subversion Client\svnversion.exe" -n $(SolutionDir)

在构建时,我可以看到正确的修订号返回到output 控制台。

现在的问题是,如何将此值存储到可在代码中使用的变量中?

我尝试定义一个预编译器变量 (_SVNREV) 并使用它直接从 pre-build 事件框保存上述 cmd 的结果,但这不起作用。

_SVNREV="C:\Program Files\CollabNet\Subversion Client\svnversion.exe" -n $(SolutionDir)
%_SVNREV%="C:\Program Files\CollabNet\Subversion Client\svnversion.exe" -n $(SolutionDir)
%_SVNREV="C:\Program Files\CollabNet\Subversion Client\svnversion.exe" -n $(SolutionDir)
$(_SVNREV)="C:\Program Files\CollabNet\Subversion Client\svnversion.exe" -n $(SolutionDir)

这些都不起作用。

解决方案: 我无处可去,试图从 VS 环境中更新变量。所以我采取了另一条路线,调用脚本作为预构建步骤,获取工作副本的 svn 修订版,然后使用该信息创建头文件。

这里是svnrev.bat 供任何感兴趣的人使用:

@echo off
set cmd="C:\"Program Files\CollabNet\Subversion Client"\svnversion.exe -n %1 "
set versionfile=%1/version.h
FOR /F %%i IN ('%cmd%') DO SET SVNVER=%%i

echo Detected program revision %SVNVER% in %1
echo #pragma once > %versionfile%
echo #define _SVNVER "%SVNVER%" >> %versionfile%

【问题讨论】:

  • 您错过了“svn 关键字替换”还是我错过了您的问题的重点?
  • 'svn 关键字替换'只会在您将文件提交到 svn 时发生。然后 svn 将用它的值替换一个保留变量。这在这种情况下不起作用。
  • 如何设置客户端更新后和提交后挂钩? TortoiseSVN 有他们。 Hooks 协同工作,更新同一个变量,即 SVN 修订版。
  • 另外,请参阅这个可能相关问题的答案:*.com/q/2738673/395718

标签: c++ visual-studio-2010 svn continuous-integration


【解决方案1】:

到目前为止我想出的最好的猜测是在包含 svnversion 的预构建事件中生成一个头文件。

例如我创建了一个批处理脚本version.bat:

@echo off
FOR /F "tokens=*" %%i IN ('call svnversion') DO echo #define SVNVERSION "%%i" > svnversion.h

无论我想获得 svnversion,我只需 #include "svnversion.h"

【讨论】:

    【解决方案2】:

    如果您正在构建,您应该有一个标准的构建系统。我推荐使用Jenkins。它是开源的,易于使用。

    Jenkins 的巧妙技巧之一是插入一些不错的环境变量供您使用:

    • SVN_REVISION - Subversion 修订号
    • BUILD_NUMBER - Jenkins 中的内部版本号
    • JOB_NAME - Jenkins 中的作业名称

    一旦您开始使用 Jenkins 进行构建,后两个环境变量可能会变得比 Subversion 修订本身更有价值,因为后两个会将您的代码链接回项目以及各种有用的信息。

    Jenkins 是一个持续构建引擎。您可以设置 Jenkins 作业以在有结帐时或一天中的特定时间构建命令。您甚至可以通过 URL 上的 wget 发送构建命令。

    通过使用构建服务器,您可以消除特定系统的配置对构建产生某种副作用的可能性。构建服务器是已知配置,将生成您的官方构建。

    这比您可能想知道的要多一点。 (具体来说,您可以使用svnversion 命令检索修订号,然后从那里继续)。但是,它将大大改善您的构建过程。

    【讨论】:

    • 感谢您,我们确实使用了 Jenkins。 问题 是这些变量在 Jenkins 中仅可用一次,即在提交代码时。也是同样的问题,那么如何在编译时将这些变量传递给源代码呢?
    • Jenkins 不检查代码并编译吗?那时 Jenkins 将插入修订号。当开发人员进行构建时,我会检查 SVN_REVISION 是否已设置。如果没有,则设置为 dev build。这样,我知道构建是来自 Jenkins(因此是官方的)还是来自开发人员。此外,在提交代码之前,您真的不知道修订版。否则,您将获得开发人员从中签出的版本号,其中不包括他们的更改。
    【解决方案3】:

    您可以运行打包在批处理文件中的命令。批处理文件可以生成像 version.h 这样的头文件,其中包含版本字符串:

    #define SVN_REV 12345
    

    “#define SVN_REV”由批处理脚本回显。 SVN rev 来自您拥有的命令。

    现在您可以在代码中包含此标头并根据需要使用#define。

    【讨论】:

      【解决方案4】:

      我见过人们解析 svn 信息以获得版本号并将其写入文件,然后设置编译以将文件添加到编译后的代码中。

      关于 SVN 的棘手问题:在旧版本中(每个子目录中都有一个 .svn 文件),版本号只能保证项目根目录的正确性。任何其他目录都将包含该子树中最后一次提交的版本号。我不知道你使用的是什么版本,但如果你是几个 revs back,请注意这一点!

      【讨论】: