从qmake到cmake:Qt6项目构建迁移实战指南

张开发
2026/4/10 3:57:08 15 分钟阅读

分享文章

从qmake到cmake:Qt6项目构建迁移实战指南
1. 为什么需要从qmake迁移到cmake如果你还在用qmake管理Qt项目现在是时候考虑切换到cmake了。Qt官方从Qt6开始已经明确将cmake作为首选构建工具qmake虽然还能用但新特性都会优先支持cmake。我最近把几个老项目从qmake迁移到cmake整个过程比想象中顺利得多。迁移的主要原因有三个首先是官方支持力度Qt Creator对cmake项目的支持越来越完善其次是生态兼容性现在大多数C库都优先提供cmake支持最后是功能强大cmake的模块化设计让复杂项目更容易管理。举个例子之前用qmake处理多国语言翻译要写一堆复杂的脚本现在cmake只需要几行配置就能自动调用Qt Linguist工具链。2. 迁移前的准备工作2.1 环境检查清单在开始迁移前建议先做好这些准备安装最新版Qt6至少6.2以上版本确保cmake版本≥3.14我推荐用3.21备份现有qmake项目.pro文件很重要准备一个干净的构建目录实测发现直接用Qt Creator创建新cmake项目再逐步迁移旧代码是最稳妥的做法。千万别在原项目目录直接修改我吃过这个亏——新旧构建系统冲突会导致各种诡异问题。2.2 项目结构对比qmake和cmake的项目结构差异很大。典型的qmake项目是这样的project/ ├── main.cpp ├── widget.cpp ├── widget.h ├── forms/ │ └── mainwindow.ui └── resources.qrc对应的cmake项目应该调整为project/ ├── CMakeLists.txt ├── src/ │ ├── main.cpp │ └── gui/ │ ├── widget.cpp │ └── widget.h ├── ui/ │ └── mainwindow.ui └── res/ └── resources.qrc关键变化是把源代码放到src子目录界面文件放到ui目录资源文件放到res目录。这种结构cmake处理起来更顺手也方便后续扩展。3. 核心配置迁移实战3.1 基础框架搭建新建CMakeLists.txt文件从这些基础命令开始cmake_minimum_required(VERSION 3.21) project(MyApp LANGUAGES CXX) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets) qt_standard_project_setup()注意qt_standard_project_setup()这个关键命令它会自动配置Qt项目需要的各种标准设置比手动配置省心很多。我迁移的第一个项目没加这行结果调试了半天MOC问题。3.2 预处理命令配置qmake会自动处理moc、uic和rcc但在cmake中需要显式声明set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOUIC ON) set(CMAKE_AUTORCC ON) set(CMAKE_AUTOUIC_SEARCH_PATHS ${CMAKE_CURRENT_SOURCE_DIR}/ui)特别提醒AUTOUIC_SEARCH_PATHS要指向你的ui文件目录否则会找不到.ui文件。我在Windows平台迁移时就踩过这个坑错误提示非常隐晦。3.3 可执行文件定义qmake的TARGET对应cmake的add_executable但有重要区别file(GLOB_RECURSE SOURCES src/*.cpp src/*.h) file(GLOB_RECURSE FORMS ui/*.ui) file(GLOB_RECURSE RESOURCES res/*.qrc) qt_add_executable(MyApp ${SOURCES} ${FORMS} ${RESOURCES} )这里强烈建议用qt_add_executable代替标准add_executable前者会处理Qt特有的编译需求。有个细节要注意如果项目包含Q_OBJECT的类必须确保头文件也在SOURCE列表中否则MOC处理会失败。4. 高级功能迁移技巧4.1 第三方库集成以前用qmake链接库是这样的LIBS -L/path/to/lib -lqwt在cmake中应该这样写find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets) target_link_libraries(MyApp PRIVATE Qt6::Core Qt6::Gui Qt6::Widgets )对于像QWT这样的第三方库现在vcpkg提供了很好的支持find_package(unofficial-qwt CONFIG REQUIRED) target_link_libraries(MyApp PRIVATE unofficial::qwt::qwt)4.2 多国语言支持qmake的翻译系统在cmake中变得更简洁qt_standard_project_setup(I18N_TRANSLATED_LANGUAGES zh_CN en_US) qt_add_translations(MyApp TS_FILE_BASE myapp TS_FILE_DIR translations RESOURCE_PREFIX /i18n )这样配置后cmake会自动调用lupdate和lrelease处理.ts文件。我在迁移时发现原来需要200多行脚本的翻译流程现在20行cmake就搞定了。4.3 资源文件处理qmake的资源系统在cmake中有两种实现方式。传统qrc文件方式set(CMAKE_AUTORCC ON) qt_add_executable(MyApp ${SOURCES} res/resources.qrc)或者直接用cmake命令管理qt_add_resources(MyApp icons PREFIX /icons FILES res/icons/home.png res/icons/settings.png )个人建议小型项目用qrc文件大型项目用qt_add_resources后者在资源很多时编译速度更快。5. 常见问题解决方案5.1 插件部署问题Windows平台最头疼的就是插件部署。用windeployqt可以自动化解决add_custom_command(TARGET MyApp POST_BUILD COMMAND Qt6::windeployqt --qmldir ${CMAKE_CURRENT_SOURCE_DIR}/qml $TARGET_FILE:MyApp )这个命令会在编译完成后自动复制所有依赖的Qt DLL和插件。我在迁移一个Qt Quick项目时手动复制插件花了半天用这行命令后完全自动化了。5.2 控制台窗口隐藏GUI程序附带控制台很烦人这样解决set_target_properties(MyApp PROPERTIES WIN32_EXECUTABLE TRUE MACOSX_BUNDLE TRUE )一个配置同时解决Windows和macOS的平台特性比qmake的CONFIG console简单直观得多。5.3 版本号管理qmake的VERSION变量在cmake中这样实现project(MyApp VERSION 1.0.0 LANGUAGES CXX) configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/version.h.in ${CMAKE_CURRENT_BINARY_DIR}/version.h )配合version.h.in模板文件#define MYAPP_VERSION_MAJOR PROJECT_VERSION_MAJOR #define MYAPP_VERSION_MINOR PROJECT_VERSION_MINOR #define MYAPP_VERSION_PATCH PROJECT_VERSION_PATCH6. 迁移后的验证策略6.1 构建验证清单迁移完成后建议检查这些点所有UI文件是否正常编译资源文件是否能正确加载Q_OBJECT类是否正常触发moc翻译文件是否嵌入可执行程序在clean构建下是否能正常编译我建立了一个简单的测试脚本用ctest实现自动化验证enable_testing() add_test(NAME RunMyApp COMMAND MyApp --test)6.2 性能对比从qmake切换到cmake后我观察到这些变化首次配置时间增加约20%增量构建速度提升30%多核编译利用率更好依赖管理更精确特别是在大型项目上cmake的并行编译优势非常明显。我的一个包含200多个源文件的项目全量构建时间从4分钟降到2分半。6.3 调试技巧遇到问题时这些cmake命令很有用cmake --build . --verbose # 查看详细构建日志 cmake -DCMAKE_EXPORT_COMPILE_COMMANDSON # 生成编译数据库 cmake --graphvizgraph.dot # 生成依赖关系图对于Qt特有的问题可以检查autogen目录下的中间文件这些是moc/uic/rcc生成的代码经常藏着问题的线索。

更多文章