解决Linux中为特定Qt版本编译安装Qt Quick Dialogs库

问题背景

在 Qt QML 工程开发过程中,我一开始是用交叉编译环境把程序跑在 arm 开发板上。后来为了更方便地看桌面端 UI 效果,切回了本机桌面环境构建,结果程序在启动时直接报错:

1
module "QtQuick.Dialogs" is not installed

这个问题看起来像是“模块没装”,但真正排查下来,更多时候不是没装,而是当前使用的 Qt 版本找不到和自己匹配的 QML 模块

错误原因分析

我这里的问题核心有两个:

  1. 系统里确实有 QtQuick.Dialogs
  2. 但系统包安装的是 Ubuntu 自带 Qt 版本对应的模块
  3. 项目实际使用的是另外一个单独安装的 Qt 版本

也就是说,程序构建和运行时使用的 Qt,与系统包里的 Qt 并不是一套环境

这种情况下,哪怕你已经执行过:

1
sudo apt install qml-module-qtquick-dialogs

项目仍然可能继续报错。

先确认当前项目到底用了哪个 Qt

在动手编译模块之前,最好先把当前 Qt 环境查清楚,不然后面很容易装错地方。

1. 查看 qmake 版本

1
2
qmake -v
which qmake

如果你机器上装了多个 Qt,这两条命令很重要。
很多时候 Creator 里选的是一个 Kit,终端里 qmake 指向的却是另一个版本。

2. 查看 QML 模块安装路径

1
/path/to/Qt5.15.2/bin/qmake -query QT_INSTALL_QML

输出的目录一般类似这样:

1
/path/to/Qt5.15.2/qml

接着检查目标模块是否真的存在:

1
ls /path/to/Qt5.15.2/qml/QtQuick/Dialogs

如果这里不存在对应目录,或者目录里内容明显不完整,那问题就比较明确了。

方法一:直接安装系统包(不适用我的场景)

最先想到的方式当然还是系统包管理器:

1
sudo apt install qml-module-qtquick-dialogs

结果

这个方法在“项目本来就使用系统 Qt”的情况下往往是有效的。
但我这里桌面调试使用的是单独安装的 Qt 5.15.2,而 Ubuntu 20.04 自带的是另一套 Qt 版本,所以装完以后仍然报错。

原因

因为 QML 模块最终是要放到当前这套 Qt 的 QML 搜索路径下的,而不是只要系统里有一个同名模块就行。

方法二:手动编译与当前 Qt 版本匹配的模块

这个方法虽然步骤多一点,但对“多 Qt 版本并存”的环境更稳。

1. 下载对应版本源码

先去 Qt 官方 submodules 页面,下载和自己 Qt 主版本完全一致的源码包。
比如我的环境是 Qt 5.15.2,示例命令如下:

1
wget https://download.qt.io/official_releases/qt/5.15/5.15.2/submodules/qtquickcontrols2-everywhere-src-5.15.2.tar.xz

这里最重要的一点不是包名,而是版本一定要对上
如果你的项目是别的版本,比如 5.12.x 或 5.15.10,就应该下载对应版本的源码。

2. 解压并准备构建目录

1
2
3
4
tar -xvf qtquickcontrols2-everywhere-src-5.15.2.tar.xz
cd qtquickcontrols2-everywhere-src-5.15.2
mkdir build
cd build

3. 使用目标 Qt 的 qmake 配置

这一点也很关键,不要直接用系统默认 qmake

1
/path/to/Qt5.15.2/bin/qmake ..

如果这里用错了 qmake,后面即使编译成功,也大概率会装进另一套 Qt 目录,等于白做。

4. 编译

1
make -j$(nproc)

5. 安装

这一步原来最容易漏掉,makemake install,模块通常不会出现在目标 Qt 的 qml 目录里

1
make install

如果你的 Qt 安装目录没有写权限,就加上 sudo

1
sudo make install

6. 再次验证

安装完成后,再检查一次:

1
ls /path/to/Qt5.15.2/qml/QtQuick/Dialogs

如果目录已经生成,再重新运行项目,通常这个报错就会消失。

如果还是报错,可以继续检查这几项

1. Creator 里 Kit 选错了

代码能编过,但运行时报模块缺失,很多时候是因为运行时用的不是你以为的那套 Qt。

2. QML 导入路径没有带上

有些项目会手动设置 QML2_IMPORT_PATH,如果路径没配对,模块即使已经装好了,程序也未必找得到。

可以临时打印一下:

1
echo $QML2_IMPORT_PATH

3. import 版本写得太死

例如 QML 里写了:

1
import QtQuick.Dialogs 1.3

那就要确认你装进去的模块是否真的能满足这个版本号要求。

一个更稳的排查思路

后来我基本按下面这个顺序排:

  1. 先看当前项目实际使用的是哪套 Qt
  2. 再看这套 Qt 的 QT_INSTALL_QML 路径
  3. 检查 QtQuick/Dialogs 是否存在
  4. 如果没有,就编译和该 Qt 版本匹配的模块
  5. 编译后一定记得 make install
  6. 最后再回到 Creator 或命令行重新运行程序验证

这样比一上来就装系统包更省时间。

总结

module "QtQuick.Dialogs" is not installed 这个错误,很多时候不是“系统没装”,而是项目使用的 Qt 环境里没有对应版本的模块
如果机器上只装了一套系统 Qt,用包管理器安装通常够用;但如果项目依赖的是另一套独立 Qt,最稳的办法还是下载对应版本源码,使用对应版本的 qmake 编译并执行 make install
把“Qt 版本”和“QML 模块安装路径”这两件事先搞清楚,问题就会简单很多。