【问题标题】:Automatic increment of build number in Qt Creator在 Qt Creator 中自动增加内部版本号
【发布时间】:2010-11-27 20:56:59
【问题描述】:

我想在 C++ 源代码中有一个变量(或 #define),每次我使用 Qt Creator 构建源代码时它都会递增。有什么办法可以做到这一点,也许是一些 Qt Creator 插件或类似的?如果我在命令行上使用“make”来构建,是否有办法做到这一点?

【问题讨论】:

    标签: c++ qt makefile qt-creator


    【解决方案1】:

    在您的 .pro 文件中,您可以创建一个包含命令行程序结果的变量。然后,您可以使用它来创建定义。

    BUILDNO = $$(command_to_get_the_build_number)
    DEFINES += BUILD=$${BUILDNO}
    

    如果你只想要一个简单的递增数字,你可以使用一个非常简单的脚本:

    #!/bin/bash
    number=`cat build_number`
    let number += 1
    echo "$number" | tee build_number #<-- output and save the number back to file
    

    我应该注意,这会导致每次构建时构建编号都会增加,并且如果您尝试构建但失败也会增加。更好的方法是根据代码的状态获取内部版本号,许多版本控制工具可以为您获取一个文本字符串,如果不是数字的话。

    【讨论】:

    • 我真的希望每次构建而不是每次存储库提交都增加。这回答了我的问题。
    • 我正在使用自己的 Qt+QMake 方案:indiocolifax86.wordpress.com/2010/05/22/…
    • 性感的 .bat 版本 :) @echo off set /p var= ver.txt (只需创建 ver.txt里面有0)
    • 不应该是$$system(./command_to_get_the_build_number)吗?
    • @mmutz:这取决于你想要什么。在我的脑海中,如果你使用$$system,它只会在 qmake 运行以生成 Makefile 时执行。另一方面,如果你按照我做的那样做,qmake 会将命令嵌入到 Makefile 中,以便在运行 make 时运行。
    【解决方案2】:

    Joerg Beutel 改进的解决方案https://stackoverflow.com/a/5967447/1619432 的 Windows 等效项:

    .pro:

    build_nr.commands = build_inc.bat
    build_nr.depends = FORCE
    QMAKE_EXTRA_TARGETS += build_nr
    PRE_TARGETDEPS += build_nr
    
    HEADERS  += build.h
    

    build_inc.bat:

    @echo off 
    set /p var= <build.txt 
    set /a var= %var%+1 
    echo %var% >build.txt
    echo #define BUILD %var% >build.h
    echo %var%
    

    用法

    #include "build.h"
    ...
    qDebug() << "Build number:" << BUILD;
    

    【讨论】:

    • 另见 qtcreator.blogspot.de/2009/10/… 以获得更精细的包含(使用自定义程序生成头文件)。
    • 它只有在我这样写时才有效build_nr.commands = $$PWD/build_inc.bat
    【解决方案3】:

    正如我之前写的,经过一些测试后,我发现原来的解决方案存在问题,因为每次新构建完成时版本号都不会更新。在很多情况下,我编辑了一个源文件,运行构建,但仍然得到相同的构建号......构建过程只是决定没有任何改变,并跳过了更新构建号的步骤。我首先试图找到一种方法来强制执行该步骤,但无法弄清楚。最后我决定走一条不同的路。现在我使用脚本生成头文件 build_number.h 包含一个 #define BUILD,后面有更新的数字。所以现在对 Calebs 脚本进行了一些修改(build_number.sh):

    #!/bin/bash
    number=`cat build_number`
    let number++
    echo "$number" | tee build_number #<-- output and save the number back to file
    echo "#define BUILD ""$number" | tee ../MyProject/build_number.h
    

    递增的数字仍存储在名为build_number 的文件中。我本可以通过解析生成的头文件中的数字来避免第三个文件,但我决定反对它。请注意,脚本和生成的标头位于项目目录中,而build_number 文件位于构建目录中。这并不完美,但我可以忍受。

    为了把事情放在一起,现在还有一些事情要做。首先需要将生成的头文件添加到 Qt Designer 中的项目中...右键单击 Header-Files 和“添加现有文件”。其次,它必须包含在 C++ 文件中,在该文件中可以访问 BUILD 定义...#include "build_number.h" ...最后但并非最不重要的是,必须对项目文件进行一些添加(MyProject.pro)。请注意,我从 Calebs 解决方案中删除了这些内容,所以我们从头开始:

    build_nr.commands = ../MyProject/build_number.sh
    build_nr.depends = FORCE
    QMAKE_EXTRA_TARGETS += build_nr
    PRE_TARGETDEPS += build_nr
    

    这些行(我将它们放在 HEADERS 部分之前)强制执行脚本,该脚本从build_number 读取最后一个内部版本号,递增它,将其写回并生成build_number.h 文件的更新版本.由于这是项目源代码的一部分,因此每次都会将新值链接到代码中。

    有一件事要提一下 - 现在构建过程是永远的,因为他们认为没有任何改变。因此,即使您保持代码不变,新的 make 运行也会生成一个新的版本号并构建一个新的二进制文件。旧解决方案在代码更改时留下了数字,即使源代码未更改,这个新解决方案也会强制构建新版本,因为我强制更改那个头文件。有人会更喜欢介于两者之间的东西,但由于标头仅包含在一个地方,因此重建速度非常快并且不会造成太大伤害。但是,如果有人知道如何两全其美,请提出建议。至少现在我不会有两个具有相同版本号的不同二进制文件。

    【讨论】:

      【解决方案4】:

      Caleb 的建议很棒,但在我的情况下并没有“开箱即用”。相反,我遇到了一些错误,并且需要一些阅读才能修复它们。变化非常小。我在 Ubuntu Linux 上使用 Qt 4.7 ...如果您相信的话,第一个更改是在 shell 脚本中从 let number += 1let number++ ...我通常使用/编程 Windoze,所以我可以'无法解释这一点,但是当我在原始情况下从命令行(shell 提示符)运行脚本时,我收到错误报告,在更改后的情况下一切顺利,并返回递增的数字...

      由于 Caleb 没有完全报告它 - 我使用 build_number.sh 作为 shell 脚本的名称,并创建了另一个名称为 build_number 的文件(没有 .sh)并在里面只放了一个零,没有别的。

      通过将 Qt 项目文件中的 BUILDNO = $$(command_to_get_the_build_number) 替换为 BUILDNO = $$system(./build_number.sh),修复了最后一个也是最令人讨厌的错误。请注意$$ 后面的system 和文件名前面所需的./。后者对于普通的 Linux 用户来说是基本的,但对于 Windows 用户来说则不然。

      希望这能让像我这样不熟悉这一切的人更直接。如果您寻求 qmake,可以在 Qt Designer 帮助部分阅读更多内容,包括函数参考、高级使用等。

      哦,最后一句话...我还不得不将DEFINES += -DBUILD=$${BUILDNO} 更改为DEFINES += BUILD=$${BUILDNO},所以-D 消失了。在您的 C++ 代码中,您将使用 BUILD,就好像您在文件顶部写了 #define BUILD 1234

      【讨论】:

      • 这是关于-D 的一个很好的说明。我将编辑我的答案以修复它。
      • 经过一些测试,现在很明显这个解决方案并不完美,因为在很多情况下,qmake 步骤在构建期间没有执行,因为“配置没有改变”。 qmake 构建用于构建应用程序的 Makefile,为此它还解释我们写入 *.pro 文件的内容,但只解释一次。在 Makefile 中,我们找到 -DBUILD 29 而不是 BUILD build_number.sh ...在 Makefile 本身中写入内容不是解决方案,因为在执行 qmake 时它会被覆盖。您可以从 Designer/Build 菜单执行 qmake,但这不是自动的。需要解决方案!
      【解决方案5】:

      这是我基于handle's solution 提出的Win7 解决方案。 此解决方案还使 Windows 在您右键单击您的目标时提供您的版本,然后选择属性 |细节。它适用于 Win7,可能是大多数早期版本。

      好的,你自己做 build_inc.bat:

      @echo off
      copy /b myapp.rc +,,
      set /p var= <build.txt 
      set /a var= %var%+1 
      echo %var% >build.txt
      echo #define BUILD %var% >build.h
      

      并将其放入您的项目文件夹中。 (copy /b myapp.rc +,, 是令人费解的“触摸”Microsoft-eese - 更新文件的时间戳。)到目前为止,一切都很好 - 那又如何?!!

      如果您不需要编码到二进制文件中的版本,这部分是可选的。创建一个 .rc 文件,例如:

      #include "build.h"
      
      1 VERSIONINFO
      FILEFLAGS 32
      FILEVERSION 1, 0, BUILD, 0
      PRODUCTVERSION 1, 0, BUILD, 0
      FILEOS 4
      FILETYPE 1
      
      {
          BLOCK "StringFileInfo"
          {
              BLOCK "040904B0"
              {
                  VALUE "FileDescription", "program"
                  VALUE "OriginalFilename", "program.exe"
                  VALUE "CompanyName", "you"
                  VALUE "FileVersion", "Release"
                  VALUE "LegalCopyright", "Copyright (c) 2016, you, fool!"
                  VALUE "ProductName", "Yer proggie"
                  VALUE "ProductVersion", "Release"
              }
          }
          BLOCK "VarFileInfo"
          {
              VALUE "Translation", 0x0409, 0x04B0
          }
      }
      

      此处提供了更完整的版本:Versioning DLLs。顺便说一句:如果没有 VarFileInfo 块,它将无法工作。此 .rc 用于诸如右键单击并在属性 | 中获取此信息之类的内容。细节。我有一个用于此信息和应用程序图标的 M$ .rc 文件,并在资源下的 Qt Creator 中添加其他资源。

      不是那么可选:这是我花了一些时间寻找的部分。在 Qt Creator 中,打开您的项目,单击小计算机图标并将其置于发布模式。点击“项目”。单击“添加构建步骤”,选择自定义流程步骤,然后单击帽子图标“^”,直到它位于列表顶部。假设您已将 .rc 命名为“myapp.rc”。使构建步骤如下所示:

      Command: cmd.exe
      Arguments:/c build_inc.bat
      Working Directory: %{CurrentProject:Path}
      

      虽然基于 qmake 的版本可能在命令行或从 IDE 调用的命令行工具中运行良好,但我相信在 Qt Creator 中,构建步骤更可取。 Qt Creator 实际上并不为每个构建运行 qmake。但是每次构建都会运行构建步骤。

      现在,将其添加到您的 .pro 文件中:

      RC_FILE +=  myapp.rc
      

      另外,将 myapp.rc 添加到您的项目中。它会显示在“其他文件”下。

      现在重建。每次重建都会触发资源文件的触摸,从而每次都运行“rc”。否则,内部版本号将不会被编码为二进制权限。它对我来说运行得很快。每次重建都会增加这个数字。我只是费心将它们添加到“发布”版本中;所以调试版本不会增加这个。他们只会使用上次构建的编号。我相信,您需要在发布时运行一次以避免错误。这无需每次在 Qt Creator 中单独重新运行 qmake 即可工作;并且每次都会给你一个不同的版本号。它不会触发任何其他重新编译。你有每次运行“rc”和链接的开销,而不是如果一切都是最新的则什么都不做;但是OTOH,我只为发布版本做这件事;无论如何,您几乎总是链接构建或运行;再说一遍,“rc”很快。

      可选:您可以在您的版本中将 BUILD 预处理器符号移动到您想要的任何位置。 #. (注意:您也可以使用以下内容添加您的应用程序图标:

      IDI_ICON1 ICON DISCARDABLE "Icons/myicon.ico"
      

      这使得它甚至在文件运行之前就显示在资源管理器中。)

      您也可以在 Qt Creator 中正式将“build.h”添加到您的项目中,将其包含在您要使用 build # 的文件中,并将其用作字符串,例如与:

      #include <QDebug>
      #include "build.h"
      
      #define STR_EXPAND(tok) #tok
      #define STR(tok) STR_EXPAND(tok)
      
      qDebug() << QString("(build ")+STR(BUILD)+")";
      

      我刚刚注意到一个副作用:如果你这样做,它会在每次发布之前重建。我想这还不算太糟糕的代价。我想我总是可以将运行时复制到发布目录中,然后从资源管理器中运行它;或者只是忍受我的 about.h 的额外编译、“rc”的运行以及每次运行在发行版中的链接。就此而言,我可以创建一个外部工具来使用键盘快捷键运行它。我当然愿意对此进行任何改进。目前,我不打扰,因为只是编译“about.cpp”,运行“rc”并与每次运行链接并不需要很长时间。不过,人们:自动构建编号!

      ☮!

      编辑:可选:为了让它仅在您构建或重新构建项目时增加构建号,而不是在您运行它时(即使构建总是在发布中发生),请转到项目 |构建和运行 |运行,点击“Add a Deploy Step”,选择“Custom Process Step”:

      Command: cmd.exe
      Arguments: /c if exist build.old copy /y build.old build.txt
      Working Directory: %{CurrentProject:Path}
      

      然后,添加

      copy /y build.txt build.old
      

      在.bat 文件中@echo off 之后。甚至可以制作自定义的新项目模板,尽管涉及到:Extending Qt Creator Manual

      编辑:我现在使用一个,而不是两个自定义构建步骤。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-08-21
        • 2011-03-06
        • 1970-01-01
        • 2023-03-14
        相关资源
        最近更新 更多