欢迎光临
我们一直在努力

管理多套 Qt / C++ 构建、编译、运行环境的最佳实践

相信大多数 Qt / C++ 开发者都不可避免地会在本地安装和使用多套构建、编译、运行环境,这会带来一个普遍的痛点:如何在 Windows 上合理地管理和使用多套 Qt / C++ 环境?本文会分享一些典型场景下的推荐做法以及一些实用的脚本,应该对你有所启发和帮助。

1. 典型状况和诉求

从大的方面看, 在 Windows 上 Qt / C++ 环境有两类独立的堆栈,它们分别是:

堆栈名称组成工具
MinGW 堆栈 CMake + Ninja + MinGW + MinGW 版 Qt
MSVC 堆栈 CMake + Ninja + MSVC + MSVC 版 Qt

关于这类堆栈有一个重要的知识点:

每个版本的 Qt 都有 MinGw 和 MSVC 两种发行版,它们分别是基于 MinGw 和 MSVC 编译构建的,MSVC 版本的 Qt 只能配合 MSVC 编译器使用,MinGW 版本的 Qt 只能配合 MinGW 编译器使用,二者不能混用

MinGW 堆栈的工具会相对轻量一些,安装和使用都比较方便,在我们刚开始接触 Qt 时,使用这套组合可以胜任大多数的 Qt 项目,但是,或早或晚,我们会遇到一些 Qt 项目,它们会使用一些只在 MSVC 版 Qt 中才有的模块(例如:WebEngine),这些模块在 MinGW 版本的 Qt 中没有,这时,我们将不得不安装 MSVC 版本的 Qt 和 MSVC 本身(Microsoft Build Tools)。这样,在你的本地环境将会有两套 Qt,以下展示了两套 Qt 的示例安装位置,也是后面实验会使用到的两个重要路径:

Qt SDK安装目录
MinGW 版 Qt C:\\Lib\\Qt\\6.10.2\\mingw_64
MSVC 版 Qt C:\\Lib\\Qt\\6.10.2\\msvc2022_64

然后是编译构建使用的 CMake、Ninjia、( MinGW | MSVC ) 三个工具,为了后面叙述简单,我们把它们合在一起称为一套“构建环境”。通常,在安装 Qt 时,Qt 内部会提供一套构建环境,如果你安装了某种 C++ IDE,如 CLion,通常在它们的安装目录下也会存在一套构建环境,而很多时候,不少开发者习惯在本地安装独立的 CMake、Ninjia、MinGW,这又形成了一套构建环境。我的人个电脑目前就是这种情况,以下就是我本机上三套构建环境的信息:

工具本地构建环境CLion 内置构建环境Qt 内置构建环境
CMake C:\\Lib\\CMake C:\\Lib\\CLion\\bin\\cmake\\win\\x64 C:\\Lib\\Qt\\Tools\\CMake_64
Ninja C:\\Lib\\Ninja C:\\Lib\\CLion\\bin\\ninja\\win\\x64 C:\\Lib\\Qt\\Tools\\Ninja
MinGW C:\\Lib\\mingw64 C:\\Lib\\CLion\\bin\\mingw C:\\Lib\\Qt\\Tools\\mingw1310_64

但是 MSVC 会比较不一样,因为它很“重”,一般不会像 MinGW 那样可以安装多套,通常在系统中只有一套:

工具系统唯一环境
MSVC C:\\Program Files (x86)\\Microsoft Visual Studio\\2022\\BuildTools\\VC\\Tools\\MSVC\\14.37.32822

面对这些环境,很多开发者需要考虑怎样使用它们,因为我们编写的程序有时候是在 IDE 中编译运行的,又时候我又需要使用命令行编译运行,这就会涉及到:**如何确定是在那套构建环境下工作的?如果环境不一致,如何进行切换?从系统全局考虑怎样配置最好?**这就是我们后面要回答的问题。

此外,为了方便介绍,我们需要一个 Qt 示例项目来做演示,本文我们选择安装 Qt 时自带的一个 Example 项目 Notepad,为了不对原始代码造成破坏,我们会拷贝一份出来,将拷贝后的目录作为测试项目的根目录:

测试项目原始位置拷贝位置(实际测试项目根目录)
Notepad C:\\Lib\\Qt\\Examples\\Qt-6.10.2\\widgets\\tutorials\\notepad C:@Workspace\\WS_Qt\\Clion-Notepad

2. 基于 MinGW 堆栈的最佳实践

我们先来看 MinGW 堆栈,我们会分别在命令行环境、Clion IDE 环境下展示如何在不同的构建环境中来回切换,最后,给出一套全局默认配置作为最佳实践。但首先,我们要明确一点:对于 CMake、Ninjia、MinGW、Qt 这四个工具,只有 CMake、Ninjia、MinGW 是可切换的“构建环境”,Qt 其实是“程序库”,不管是哪一套构建环境,它应该“总是被发现和使用”,因此,Qt 应该总是被添加入到系统的动态链接库文件搜索路径,也就是 PATH 环境变量中,防止编译和运行 Qt 程序时报错:

在这里插入图片描述

图1. 基于 MinGW 堆栈时应将 MinGW 版的 Qt 添加到 PATH 环境变量中

2.1 在命令行中切换构建环境

最初,我曾设想取消所有与 CMake、Ninjia、MinGW 相关的环境变量设置,通过在命令行中使用各种工具的绝对路径来实现环境切换,但这一尝试因为 MinGW 失败了,确切地说是不可行,具体原因参考《为什么使用 CMake 必须将 MinGW 添加进 PATH 环境变量?》。但是,在不设固定环境变量的情况下,我们还是有方法可以在不同的构建环境中切换的,那就是在当前命令行窗口添加临时的 PATH 变量(也许 toolchain 也是个方法,但我不是很感兴趣)。

以我的本地环境为例,如果我要在三套环境中分别编译 Notepad 项目,可以这样做:事先移除所有与 CMake、Ninjia、MinGW 有关的系统环境变量设置,打开新的命令行窗口,在执行构建命令前,先将目标环境中的 CMake、Ninjia、MinGW 三个工具的 bin 目录临时添加到 PATH 环境变量中,构建命令行使用到的所有工具都不使用绝对路径修饰,直接使用命令名,保证命令的可移植性。具体命令如下:

❏ 切换至本地构建环境:

set PATH=C:\\Lib\\CMake\\bin;%PATH%
set PATH=C:\\Lib\\Ninja;%PATH%
set PATH=C:\\Lib\\mingw64\\bin;%PATH%

❏ 切换至 CLion 内置构建环境:

set PATH=C:\\Lib\\CLion\\bin\\cmake\\win\\x64\\bin;%PATH%
set PATH=C:\\Lib\\CLion\\bin\\ninja\\win\\x64;%PATH%
set PATH=C:\\Lib\\CLion\\bin\\mingw\\bin;%PATH%

❏ 切换至 Qt 内置构建环境:

set PATH=C:\\Lib\\Qt\\Tools\\CMake_64\\bin;%PATH%
set PATH=C:\\Lib\\Qt\\Tools\\Ninja;%PATH%
set PATH=C:\\Lib\\Qt\\Tools\\mingw1310_64\\bin;%PATH%

切换后可以使用以下命令查看是否以生效:

where cmake.exe ninja.exe qmake.exe gcc.exe g++.exe

最后使用以下命令构建 Notepad 项目(定位至项目根目录执行):

rd /S /Q cmake-build-debug &
cmake.exe ^
-DCMAKE_BUILD_TYPE=Debug ^
-DCMAKE_MAKE_PROGRAM=ninja.exe ^
-G Ninja ^
-B cmake-build-debug &
ninja.exe -C cmake-build-debug &
.\\cmake-build-debug\\notepad.exe

2.2 在 IDE 中切换构建环境

在 IDE 中切换构建环境的操作方法因 IDE 的不同而各不相同,本文我们只讨论 CLion 的做法。CLion 没有对 Qt 做任何深度集成,它视 Qt 为普通 C++ 项目,对 Qt 项目的管理完全依赖 CMake,所以,CLion 对 Qt 项目的管理本质上和使用 CMake 命令行是一样的。

在命令行中我们是靠“设置 PATH 变量中的构建工具 bin 路径”实现环境切换的, 在 CLion 中,我可以设置多套 Toolchain 来实现相同的目标。其中,Clion 会自带一套默认的 MinGW (default) 构建环境,这个环境就是 2.1 节我们使用命令行切换的“CLion 内置构建环境”,在本节,我们会演示创建基于 “Qt 内置环境”的 Toolchain,至于基于“本地构建环境”的 Toolchain 同理可配置,但我们不再赘述。以下是具体操作:依旧是在我的本地环境,下图是 CLion 的默认构建环境( Toolchain ):

图2. CLion 在 MinGW 堆栈下提供的一套基于其内置 CMake、Ninja、MinGW 的 Toolchain

红框中的所有工具都位于 CLion 安装目录下,具体位置就是第1节表格中 “CLion 内置构建环境” 所示的位置。如果我们想在 IDE 中使用 Ot 的构建环境,可以打开 Settings,进入 Toolchains 配置页面,点加号新增一个 Toolchain,取名 MinGW (Qt),将所有的工具全部改为安装在 Qt 目录下的版本,也就是第1节表格中 “Qt 内置构建环境” 所示的位置:

图3. 在 MinGW 堆栈下自定义的一套基于 Qt 内置 CMake、Ninja、MinGW 的 Toolchain

之后,在新建或打开一个项目时,就可以在 Toolchain 的下拉列表框中选择这个 MinGW (Qt),则项目的构建环境就使用 Qt 内置的构建环境了。一个小贴士:在 CLion 中,Toolchain 是全局设置,所有项目可用,Debug 是 by project 的,一个项目一份 Debug 配置,当前项目下的 Debug 配置不会影响到其他项目。

最后,关于 Clion 切换构建环境还有一个没解释的细节:我们可以观察到在不同的 Toolchain 下,CLion 生成的 CMake 构建命令其实使用的全是绝对路径,但我相信,这并不能规避 MinGW 的 dll 库加载问题,也就是在命令行下遇到的问题,所以,只能推测说:CLion 在执行构建命令前,一定也是在某个地方将 MinGW 的 bin 目录临时添加到了 PATH 环境变量中。

2.3 全局配置建议

我们已经介绍了现状和诉求,也知道了在命令行和 IDE 中怎样切换构建环境,但这并不是我们的“日常”,通常我们不会频繁的切换构建环境,默认情况下,我们应该是在一套构建环境下工作,且一般命令行和IDE的构建环境也应该一致,那汇总这些需求,我推荐我们的整个开发环境可以这样配置:

  • 根据个人工作领域选择一套构建环境作为全局默认环境,例如以 Qt 开发为主,则推荐选择“Qt 的内置构建环境”,操作方法是:将 CMake、Ninjia、MinGW 三个工具的 bin 目录添加到 PATH 系统环境变量中(非临时),再加上之前就已存在的 Qt 的 bin 目录,最终系统的 PATH 环境变量应该是这样的:
  • 图4. 基于 MinGW 堆栈时全部的 PATH 变量设置

  • 在 IDE 一测同样把已选定构建环境的 Toolchain 设为默认,例如把前面创建的“Qt 内置构建环境”的 Toolchain 设置为默认 Toolchain,则在 IDE 中打开与新建项目会自动使用该构建环境,与全局配置、命令行环境保持一致

    图5. 基于 MinGW 堆栈时将基于“Qt 内置构建环境”的 Toolchain 设为默认

  • 如需临时切换环境,参照2.2节和2.3节,无需修改全局配置

  • 3. 基于 MSVC 堆栈的最佳实践

    接下来,我们再看 MSVC 堆栈,这会和 MinGW 堆栈有不小的差异,首先:MSVC 只有一套环境,不会像第2节中 MinGW 那样会在三套间切换,从这个角度上讲,CMake + Ninjia + MSVC 已经不是严格意义上的三套环境了;其次,MSVC 也不像 MinGW 那样是一种 standalone 的编译器,它的核心执行文件 cl.exe 也不会被添加到 PATH 环境变量中,使用它需要预设一系列的环境变量,打开 MSVC 的正确方法是:

  • 使用专有的命令行窗口 “x64 Native Tools Command Prompt for VS 2022”
  • 在普通命令行窗口中先执行一个环境初始化脚本:C:\\Program Files (x86)\\Microsoft Visual Studio\\2022\\BuildTools\\Common7\\Tools\\VsDevCmd.bat
  • 不过,Qt 库的声明逻辑还是和 MinGW 一样:不管使用那一套构建环境,Qt 应该总是被添加入到系统的动态链接库文件搜索路径,也就是 PATH 环境变量中,防止编译和运行 Qt 程序时报错,只不过,这时设置的是 MSVC 版的 Qt:

    图6. 基于 MSVC 堆栈时应将 MSVC 版的 Qt 添加到 PATH 环境变量中

    3.1 在命令行中切换构建环境

    由于 MSVC 通常只有一套环境,且 Qt 又必须是配套的 MSVC 版,则实际可切换环境的只有 CMake 和 Ninja,这已经不能算多套环境了,所以切换环境的意义并不大,但为了和 2.1 节保持一致,同时也是作一个参照,我们还是会完成相应的演示工作。和 2.1 节一样,为了干净的测试,同样事先移除所有与 CMake、Ninjia、MinGW、Qt 有关的系统环境变量设置,然后打开“开始”菜单,输入“x64 Native Tools Command Prompt for VS 2022”,即可打开一个已经初始化好 MSVC 各种环境变量的命令行窗口!可以输入命令 cl 验证环境是否就绪。与 2.1 节不同,三套环境切换的命令行都不会将 MinGW 的 bin 目录添加到 PATH 中,但也没有显式地配置 MSVC 相关的任何路径,因为系统全局只有一套 MSVC 环境,在打开“x64 Native Tools Command Prompt for VS 2022”窗口时就自动设置好了,最后,Qt 路径也改成了 MSVC 版的:

    ❏ 切换至本地构建环境(仅限 CMake、Ninja):

    set PATH=C:\\Lib\\CMake\\bin;%PATH%
    set PATH=C:\\Lib\\Ninja;%PATH%
    set PATH=C:\\Lib\\Qt\\6.10.2\\msvc2022_64\\bin;%PATH%

    ❏ 切换至 CLion 内置构建环境(仅限 CMake、Ninja):

    set PATH=C:\\Lib\\CLion\\bin\\cmake\\win\\x64\\bin;%PATH%
    set PATH=C:\\Lib\\CLion\\bin\\ninja\\win\\x64;%PATH%
    set PATH=C:\\Lib\\Qt\\6.10.2\\msvc2022_64\\bin;%PATH%

    ❏ 切换至 Qt 内置构建环境(仅限 CMake、Ninja):

    set PATH=C:\\Lib\\Qt\\Tools\\CMake_64\\bin;%PATH%
    set PATH=C:\\Lib\\Qt\\Tools\\Ninja;%PATH%
    set PATH=C:\\Lib\\Qt\\6.10.2\\msvc2022_64\\bin;%PATH%

    切换后可以使用以下命令查看是否以生效:

    where cmake.exe ninja.exe qmake.exe cl.exe gcc.exe g++.exe

    上面的检查中我们特意把 gcc.exe 和 g++.exe 加上,在移除了环境变量的情况下,系统是找不到这两个执行文件的,主要是以此宣示这是在 MSVC 的编译环境下。最后使用以下命令构建 Notepad 项目(定位至项目根目录执行):

    rd /S /Q cmake-build-debug &
    cmake.exe ^
    -DCMAKE_BUILD_TYPE=Debug ^
    -DCMAKE_MAKE_PROGRAM=ninja.exe ^
    -G Ninja ^
    -B cmake-build-debug &
    ninja.exe -C cmake-build-debug &
    .\\cmake-build-debug\\notepad.exe

    3.2 在 IDE 中切换构建环境

    这一部分的操作和 2.2 节是高度类似的,实际上,如果你本地安装了 MSVC,CLion 是可以检测到并自动生成一个名为 Visual Stutio 的 toolchain,你可以直接使用它:

    图7. CLion 在 MSVC 堆栈下提供的一套基于其内置 CMake、Ninja 的 Toolchain

    在这个默认的基于 MSVC 的环境里,CMake 和 Ninja 都是 CLion 内置的,仿照 2.2 节的做法,我们可以配置成为基于 Qt 内置的:打开 Settings,进入 Toolchains 配置页面,点加号新增一个 Toolchain,取名 Visual Studio (Qt),将CMake 和 Ninja 改为安装在 Qt 目录下的版本,也就是第1节表格中 “Qt 内置构建环境” 所示的位置:

    图8. 在 MSVC 堆栈下自定义的一套基于 Qt 内置 CMake、Ninja 的 Toolchain

    3.3 全局配置建议

    与在 MinGW 堆栈下的最佳实践类似,我们不太会频繁在不同环境下切换,所以应该有一份相对稳定的全局配置。

  • 根据个人工作领域选择一套构建环境作为全局默认环境,例如以 Qt 开发为主,则推荐选择 Qt 的内置构建环境,操作方法是:将 CMake、Ninjia 的 bin 目录添加到 PATH 系统环境变量中(非临时),MSVC 全局唯一,不需要配置。搭配工作的 MSVC 版 Qt 也是必须且唯一的,所以应该加入到 PATH 环境变量,再加上之前就已存在的 Qt 的 bin 目录,最终系统的 PATH 环境变量应该是这样的:

    图9. 基于 MSVC 堆栈时全部的 PATH 变量设置

  • IDE 同步添加选定的构建环境为一个 Toolchain,并设置为默认 Toolchain,则在 IDE 中打开与新建项目会自动使用该构建环境,与全局配置、命令行环境保持一致:

    图10. 基于 MSVC 堆栈时将基于“Qt 内置构建环境”的 Toolchain 设为默认

  • 如需临时切换环境,参照第3.2节和第3.3节,无需修改全局配置。

  • 4. MinGW 和 MSVC 双堆栈共存

    第2节和第3节都是在“单独使用 MingGW 和 MSVC 两套堆栈”时的最佳实践,如果我们需要交叉使用两套堆栈,就得考虑如何让两套环境共存且不冲突,还要能方便地在两套环境间切换。这需要考虑以下几个问题:

  • CMake、Ninjia 很容易处理,它们不受 MingGW 和 MSVC 的影响,直接统一为 Qt 内置环境,加入 PATH 环境变量即可
  • 麻烦的是 “MinGW + MinGW 版 Qt” 和 “MSVC + MSVC 版 Qt” 的切换。因为它们涉及全局 PATH 变量的设置,这个问题我的建议是:如果你不是频繁地需要的两套堆栈中间切换,那就使用图4或图9的设置,系统全局固定在一套堆栈上,需要切换时再改 PATH 环境变量,如果你需要频繁地切换,那就不要设置 Qt 和 MinGW 的 PATH 环境变量,改为在命令行窗口中使用 set 命令临时设置。
  • 赞(0)
    未经允许不得转载:171主机测评 » 管理多套 Qt / C++ 构建、编译、运行环境的最佳实践
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址