Qt RCC(资源编译器)是不确定的-如何使它确定

qt rcc (resource compiler) is non-deterministic - how to make it deterministic

本文关键字:何使它 不确定 RCC 资源 编译器 Qt      更新时间:2023-10-16

我有一个命令在我的makefile中使用Qt资源编译器。
此实用程序为传递给它的每个图像文件生成静态数组。
不幸的是,rcc.exe是不确定的:生成的.cpp文件中这些数组的顺序在每次调用时是不同的。

我运行了三次:

>C:rcc.exe -name lookupmodels lookupmodels.qrc -o .qrc/qrc_lookupmodels-1.cpp
>C:rcc.exe -name lookupmodels lookupmodels.qrc -o .qrc/qrc_lookupmodels-2.cpp
>C:rcc.exe -name lookupmodels lookupmodels.qrc -o .qrc/qrc_lookupmodels-3.cpp

.qrc文件为:

<RCC>
    <qresource prefix="/">
        <file>datapool_pdal1.csv</file>
        <file>events_Ic.csv</file>
        <file>events_Evt.csv</file>
        <file>events_Other.csv</file>
        <file>key_events.csv</file>
        <file>loglevel_DPvalues.csv</file>
        <file>loglevel_Evtvalues.csv</file>
        <file>log_freqDP.csv</file>
    </qresource>
</RCC>

作为static const unsigned char的数组,.cpp文件非常大,所以我不会在这里展示它们,但基本问题是这些表示图像的数组的顺序在每次调用时都会发生变化。

为了比较构建与构建-特别是因为我正在切换构建系统-我需要能够比较工件

我希望它们不要改变,这样我就可以比较构建与构建之间的工件输出,看看是否有什么改变了。

这是唯一的对象文件,给我这个问题。

很可能是偶然的;在内部,rcc在某处使用QHash,它在哈希函数中使用随机种子:

http://interest.qt-project.narkive.com/HsoMhGOu/qt-resource-compiler-why-does-it-randomize-the-order-of-items

这是由于哈希随机化。这样做是为了避免DoS攻击是否可以通过调整数据来确保它始终属于相同的哈希桶。

要使哈希种子非随机(从而使rcc具有确定性),在调用rcc之前将环境变量QT_HASH_SEED设置为某个固定的数值。

默认情况下启用QHash的随机化。尽管程序不应该依赖于特定的QHash顺序,但在某些情况下,您可能临时需要确定性行为,例如调试或回归测试。要禁用随机化,请定义环境变量QT_HASH_SEED。该变量的内容被解释为十进制值,将用作qHash()的种子。或者,您可以调用qSetGlobalQHashSeed()函数。

http://doc.qt.io/qt-5/qhash.html algorithmic-complexity-attacks


无论如何,关于这个问题的补丁已经合并(更一般地说,它应该修复类似的问题,甚至在ui和moc),所以最新版本的Qt应该不会受到影响。

由于Matteo Italias的回答中提到的QT_HASH_SEED问题已经在最近的Qt版本中修复,仍然存在差异的来源(至少与一些rcc工具)。具体来说,资源文件本身的修改时间戳被嵌入到输出中(出于某种原因)。由于新的repo克隆具有新的时间戳,这可能会破坏CI/CD系统中的确定性。

解决方案是在运行rcc工具之前将所有资源文件时间戳设置为一致的值。用一个简单的bash示例来说明(这是PySide6的rcc工具和GNU/Linux的touch -根据您的情况调整):

while read -r fn; do
    touch -t 202201010000.00 "${fn}"
done < <(pyside6-rcc --list path/to/resources.qrc)
pyside6-rcc path/to/resources.qrc -o path/to/output.py # Now consistent
相关文章: