使用 CMake 编译现有的 QMake 项目

date
Sep 19, 2023
slug
use-cmake-to-compile-current-qmake-project
status
Published
summary
使用 CMake 在 Windows + Qt 5.12 + MinGW 7.3.0 下重新编译已有 Qt 项目
type
Post
tags
C/C++
使用 Qt Creator 创建的项目默认使用 QMake 编译,其制导文件名字为 ${ProjectName}.pro。下面记录使用 CMake 在 Windows + Qt 5.12 + MinGW 7.3.0 下重新编译已有 Qt 项目过程的方法。

Qt 配置

  1. 首先运行 Qt Online Installer 。如果网络状况较好,可以直接在里面安装 Qt;如果网络状况不好,仅安装 Qt Maintainence Tool 即可,可以在 Custom Installation 下取消勾选体积较大的安装部分。
  1. 如(1)无法安装 Qt,可以另外通过 aqt 安装 Qt。以 Qt 5.12 为例:
    1. pip install -U pip pip install aqtinstall
      aqt 会自动搜索更快的镜像。由于是命令行运行的,为其设置代理也比 Qt Online Installer 容易很多。接下来查询需要安装的 Qt 版本有哪些可选:
      aqt list-qt windows desktop --arch 5.12.2 > win32_mingw73 win32_msvc2017 win64_mingw73 win64_msvc2015_64 win64_msvc2017_64
      以 MinGW 的为例:
      aqt install-qt windows desktop 5.12.2 win64_mingw73 -m all
      即可完成安装。
  1. aqt 似乎不会去安装对应版本的 MinGW,此时可以用 Qt Maintainence Tool 寻找对应版本的 MinGW 来安装,这样比直接去 Source Forge 找要方便很多:
    1. notion image
      MinGW 的安装通常很快,不像 Qt 本体那样无法跑满下载速度。最后按需把安装的 Qt、编译器等手动添加到 PATH 环境变量即可(为了让 VS Code 的 CMake 找到这个 MinGW,一般要把 MinGW\bin 目录添加到 PATH)。以此法安装的 MinGW 通常位于 C:\Qt\Tools 文件夹下。

CMakeLists.txt

首先,为了保证 CMake 能正确找到这个 Qt(而不是找到 Anaconda 内置的 Qt),建议用 CMAKE_PREFIX_PATH 的方式将 Qt 的位置传递给 CMake。对于 VS Code 来说,可以通过修改 .vscode/settings.json 实现,添加如下一段即可:
"cmake.configureEnvironment": { "CMAKE_PREFIX_PATH": "C:\\Qt\\5.12.2\\mingw73_64\\lib\\cmake" }
注意把路径换成对应 Qt 文件夹下的 lib/cmake
将 QMake 的 .pro 文件翻译到 CmakeLists.txt 大体上是很简单的,可以通过 ChatGPT 完成(把整个 QMake 粘贴进去,要求翻译为 CML 即可)。经测试,ChatGPT 懂得让 CMake 调用 Qt 的 UI 生成(qt5_wrap_ui)。但还是有一些情况会被忽略,需要额外注意:
  1. 建议手动打开 moc、rcc 等功能。
    1. set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOUIC ON) set(CMAKE_AUTORCC ON)
  1. 建议额外把 CMake 的输出文件夹作为目标引入,因为 Qt 的 ui 会作为头文件生成输出文件夹(一般是 ./build 下)。
    1. target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
  1. 建议检查生成的 CML 是否添加了 RCC 生成的资源。
    1. set(RESOURCES resources/res.qrc) qt5_add_resources(RESOURCES_RCC ${RESOURCES})
完成后,正常使用 CMake(无论是直接用、通过 GUI 调用还是用 VS Code 调用都可以)编译即可。注意 CMake 调用的编译器要选择刚才单独安装的那个对应 Qt 版本的编译器。把这个编写好的 CMakeLists.txt 也放在项目的根目录。
下次开发的时候,可以通过直接右键此 CMakeLists.txt,并且选择打开方式为 Qt Creator。这样就可以用 Qt Creator 正常读取此项目,并且作开发和调试。这样打开以后,项目会默认改成用 CMake 而不是 QMake 编译。而整合开发的界面时,通过导入 CMakeLists.txt 的方式,可以将其作为子项目进行编译。

如果不用一样的编译器会怎么样?

补充一节讨论一下这个问题。
有时也不会怎么样,但没有保证。如需要更高级 C++ 的支持,Qt 5.12 / 5.14 结合 gcc 13+ 是基本能使用的。另外要注意在 Windows 上 Qt 和 Clang 不兼容,因为 Clang 使用了 UCRT,而 Qt 的 Windows 发行版都是 MSVCRT:
如果混合使用,程序能通过编译、甚至也能运行起来;但是涉及自己编写的操作 Qt 界面的代码中新建与删除 QWidget 对象时会闪退。这时候如果可以,转战 WSL 也是个不错的选择(llvm 系的编译比 gcc 快一些)。
 
If you have any questions, please contact me.