第55章:Qt项目——用find_package搞定Qt5/Qt6构建
Qt项目构建,说白了就是让CMake找到Qt的库和头文件。很多新手一上来就手动设置路径,结果换个机器就崩。我个人习惯用find_package,这是最正统的做法。
为什么非要用find_package?
你想想看,Qt的安装路径五花八门——Windows可能在C:\Qt\5.15.2,Linux可能在/usr/lib/x86_64-linux-gnu/cmake。手动写死路径?那项目基本就废了。
find_package会自动搜索系统里注册的Qt路径。我在项目中遇到过好几次,同事把Qt装到D盘,结果CMake死活找不到。其实就是没设CMAKE_PREFIX_PATH。
核心命令:
find_package(Qt5 COMPONENTS Widgets Core Gui REQUIRED)
或者Qt6版本:
find_package(Qt6 REQUIRED COMPONENTS Widgets Core Gui)
Qt5 vs Qt6,怎么选?
嗯,这里要注意。Qt6和Qt5的模块名有些变化。比如Qt5的Qt5WebEngineWidgets在Qt6里变成了Qt6WebEngineWidgets。我建议你直接写一个兼容两者的CMake脚本。
| 模块 | Qt5名称 | Qt6名称 |
|---|---|---|
| 基础控件 | Qt5::Widgets | Qt6::Widgets |
| 网络模块 | Qt5::Network | Qt6::Network |
| OpenGL | Qt5::OpenGL | Qt6::OpenGL |
| QML | Qt5::Qml | Qt6::Qml |
实战:一个完整的Qt项目CMakeLists.txt
直接上代码。这是我常用的模板,兼容Qt5和Qt6:
cmake_minimum_required(VERSION 3.16)
project(MyQtApp LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# 自动检测Qt版本
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets Core Gui)
# 如果你需要网络模块
# find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Network)
add_executable(${PROJECT_NAME}
main.cpp
mainwindow.cpp
mainwindow.h
)
target_link_libraries(${PROJECT_NAME} PRIVATE
Qt${QT_VERSION_MAJOR}::Widgets
Qt${QT_VERSION_MAJOR}::Core
Qt${QT_VERSION_MAJOR}::Gui
)
# 自动处理MOC、UIC、RCC
set_target_properties(${PROJECT_NAME} PROPERTIES
AUTOMOC ON
AUTOUIC ON
AUTORCC ON
)
这里有个小技巧:find_package(QT NAMES Qt6 Qt5)会先找Qt6,找不到再找Qt5。变量QT_VERSION_MAJOR会自动设为6或5。这样你写一次CMake,两个版本都能用。
避坑指南:我曾经在Windows上遇到find_package找不到Qt,折腾了半天。后来发现是没设CMAKE_PREFIX_PATH。你可以在CMake命令行加:
cmake -DCMAKE_PREFIX_PATH=C:/Qt/6.5.0/msvc2019_64 ..
或者在CMakeLists.txt里加:
set(CMAKE_PREFIX_PATH "C:/Qt/6.5.0/msvc2019_64")
MOC、UIC、RCC——Qt的三驾马车
Qt项目里,头文件里经常有Q_OBJECT宏,这玩意儿需要MOC(元对象编译器)处理。还有.ui文件需要UIC处理,.qrc资源文件需要RCC处理。
手动调用这些工具?太累了。CMake提供了三个开关:
- AUTOMOC ON:自动扫描头文件,发现有
Q_OBJECT就调用moc - AUTOUIC ON:自动处理
.ui文件 - AUTORCC ON:自动编译
.qrc资源文件
我个人习惯全部打开。省心。但要注意,如果你的头文件不在add_executable里列出,AUTOMOC可能找不到。所以头文件也要加进去。
SVG:find_package构建Qt项目的完整流程
常见问题与避坑
问题1:找不到Qt
我曾经在Linux上遇到find_package说找不到Qt5,但明明装了。后来发现是没装qtbase5-dev这个包。Ubuntu上要装:
sudo apt install qtbase5-dev qtchooser qt5-qmake qtbase5-dev-tools
Qt6的话:
sudo apt install qt6-base-dev
问题2:版本冲突
如果你系统里同时装了Qt5和Qt6,find_package可能会找到你不想用的版本。解决办法:
# 强制使用Qt5
find_package(Qt5 REQUIRED COMPONENTS Widgets)
# 或者强制使用Qt6
find_package(Qt6 REQUIRED COMPONENTS Widgets)
问题3:链接错误
有时候find_package成功了,但链接时报错说找不到某个符号。这通常是因为你忘了链接某个模块。比如用了QNetworkAccessManager但没链接Network模块。
我的经验是:用到了哪个Qt类,就去查它属于哪个模块。比如QJsonDocument属于Core,QWebEngineView属于WebEngineWidgets。
总结一下
用find_package构建Qt项目,说白了就是三步:
- 调用
find_package找到Qt - 用
add_executable添加源文件 - 用
target_link_libraries链接Qt模块
再加上AUTOMOC、AUTOUIC、AUTORCC三个开关,基本就齐活了。嗯,就这么简单。
对了,如果你在Windows上用MSVC,记得用cmake -G "Visual Studio 17 2022"指定生成器。不然CMake可能默认用Ninja,而Ninja不一定能找到Qt的DLL路径。我踩过这个坑,编译通过了,运行时报错说找不到Qt5Core.dll……后来老老实实设了PATH环境变量才搞定。