0%

Qt 版本和显示异常

开发 Qt 软件过程中发现折线图(Qt Charts 二维折线图)显示不全、圆环刻度值(QPainter 自绘)显示异常。

上述问题和程序运行时使用的 Qt 版本有关,但和编译时使用的 Qt 版本无关:

  • 项目源码是在 Qt 5.13.2 下构建开发的,未针对 5.12.12 做适配
  • 但使用 Qt 5.12.12 也能够编译成功;
  • 运行时必须使用 Qt 5.13.2 ,如果运行时使用 5.12.12 就会出现上述现象。

使用 Qt 5.13.2 构建的可执行文件,运行时库如果使用 5.12.12 会启动失败,报错:
undefined symbol: qt_resourceFeatureZlib, version Qt_5

在 Qt Creator 中运行、调试项目时,使用的 Qt 版本一般和编译期的版本一致,但我们可以打破这种一致性:

  • 编译时,关闭 QT.global.enabled_features = rpath 特性:此特性在 5.12.12 中默认关闭;在 5.13.2 中默认开启。
  • 运行时,修改 LD_LIBRARY_PATH 使找到的 Qt 运行时库和编译时的库版本不一致

在设备上部署软件后,如何约束运行时使用的 Qt 版本(以及第三方库):

  • 通过 -rpath 特性约束,要求设备上存在对应的目录
  • 通过 LD_LIBRARY_PATH 环境变量约束

可以使用 readelf -d a.out 查看可执行文件是否指定了运行时库的查找路径。

特性 QT.global.enabled_features

Qt Creator 如何指定 Qt 运行时库的查找路径的?关键变量 QMAKE_RPATHDIR

  1. 在 Qt Creator 中编译输出 g++ -Wl,-rpath,/opt/Qt-5.13.2/lib
  2. 由中间文件 Makefile 中 LFLAGS= 属性指定
  3. 项目 untitled.pro 中没有配置 QMAKE_RPATHDIR,使用 qmake -d 发现调用关系:
  4. qmake -spec linux-g++ 使用的 qmake.confload(qt_config)
  5. features/qt_config.prf 中调用了 mkspecs/qconfig.pri
  6. mkspecs/qconfig.pri 中设置了 QT.global.enabled_featuresQT.global.disabled_features
  7. view features/qt.prf +247 条件判断 qtConfig(rpath) 更新 QMAKE_RPATHDIR 的值

qmake -d 的执行日志:features/qt.prfQMAKE_RPATHDIR 进行赋值晚于 .pro ,所以无法在 .pro 中打印查看。

1
2
3
4
5
6
7
8
9
10
11
12
52:DEBUG 1: visiting file /usr/lib/aarch64-linux-gnu/qt5/mkspecs/linux-g++/qmake.conf
294:DEBUG 1: visiting file /usr/lib/aarch64-linux-gnu/qt5/mkspecs/features/qt_config.prf
305:DEBUG 1: visiting file /usr/lib/aarch64-linux-gnu/qt5/mkspecs/qconfig.pri
324:DEBUG 1: done visiting file /usr/lib/aarch64-linux-gnu/qt5/mkspecs/qconfig.pri
2231:DEBUG 1: done visiting file /usr/lib/aarch64-linux-gnu/qt5/mkspecs/features/qt_config.prf
2234:DEBUG 1: done visiting file /usr/lib/aarch64-linux-gnu/qt5/mkspecs/linux-g++/qmake.conf

2479:DEBUG 1: visiting file /home/lkylin/src/untitled/untitled.pro
2530:DEBUG 1: done visiting file /home/lkylin/src/untitled/untitled.pro

2843:DEBUG 1: visiting file /usr/lib/aarch64-linux-gnu/qt5/mkspecs/features/qt.prf
3660:DEBUG 1: done visiting file /usr/lib/aarch64-linux-gnu/qt5/mkspecs/features/qt.prf

关于 load() 函数和 feature 特性,查看 qmake Manual (Built-in Test Functions 章节 Advanced Usage)

Loads the feature file (.prf) specified by feature, unless the feature has already been loaded.

变量 $ORIGIN

$ORIGIN 是一个特殊变量,表示可执行文件所在的目录。

它在设置 RPATH 时非常有用,因为它允许动态库相对于可执行文件的位置进行解析。

那么,在 Qt 中如何指定 $ORIGIN 呢?