我想#define
在 C++ 源代码中有一个变量(或),每次我使用 Qt Creator 构建源代码时它都会增加。有什么办法可以做到这一点,也许是一些 Qt Creator 插件或类似的?如果我在命令行上使用“make”来构建,是否有办法做到这一点?
5 回答
在您的 .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
我应该注意,这会导致每次构建时构建编号都会增加,并且如果您尝试构建但失败也会增加。更好的方法是根据代码的状态获取内部版本号,许多版本控制工具可以为您提供一个文本字符串,如果不是数字的话。
Joerg Beutel 改进解决方案的 Windows 等效方案https://stackoverflow.com/a/5967447/1619432:
.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;
正如我之前在一些测试后所写的那样,我发现原始解决方案存在问题,因为每次完成新构建时版本号都不会更新。在很多情况下,我编辑了一个源文件,运行构建,但仍然得到相同的构建号......构建过程只是决定没有任何改变,并跳过了更新构建号的步骤。我首先试图找到一种方法来强制执行该步骤,但无法弄清楚。最后我决定走一条不同的路。现在我使用脚本生成一个头文件
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 和“添加现有文件”。其次,它必须包含在访问 BUILD 定义的 C++ 文件中#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 运行也会生成一个新的版本号并构建一个新的二进制文件。旧解决方案在代码更改时留下了数字,即使源代码未更改,这个新解决方案也会强制构建新版本,因为我强制更改那个头文件。有人会更喜欢介于两者之间的东西,但由于标头仅包含在一个地方,因此重建速度非常快并且不会造成太大伤害。但是,如果有人知道如何两全其美,请提出建议。至少现在我不会有两个具有相同版本号的不同二进制文件。
Caleb 的建议很棒,但在我的情况下并没有“开箱即用”。相反,我遇到了一些错误,并且需要一些阅读才能修复它们。变化非常小。我在 Ubuntu Linux 上使用 Qt 4.7 ......如果你相信的话,第一个变化是在 shell 脚本中从let number += 1
to let 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
after$$
和required 。./
后者对于普通的 Linux 用户来说是基本的,但对于 Windows 用户来说则不然。
希望这能让像我这样的新手更直接。如果您寻求 qmake,可以在 Qt Designer 帮助部分阅读更多内容,包括函数参考、高级使用等。
哦,最后一句话……我也不得不改成DEFINES += -DBUILD=$${BUILDNO}
,DEFINES += BUILD=$${BUILDNO}
所以-D
消失了。在您的 C++ 代码中,您可以BUILD
像#define BUILD 1234
在文件顶部那样使用。
这是我根据handle的解决方案提出的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
并将其放入您的 proj 文件夹中。(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
}
}
此处提供了更完整的版本:版本控制 DLL。顺便说一句:如果没有 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
编辑:我现在已经使它与一个,而不是两个自定义构建步骤一起工作。