用VS Code搞Qt6:编译源代码与基本配置

先说明一下,本水文老周仅讨论新版的 Qt 6,旧版的 Qt 不讨论。

尽管 Qt 有自己的开发环境,但老周必须说句不装逼的话:真的不好用。说起写代码,当然了,用记事本也能写。但是,有个高逼格的工具,写起来不仅效率高,而且舒服。

Qt 应用程序本质上就是 C++ 开发的代码,所以,不用官方工具是没有问题的。老周第一个想到的,不用猜,必是 VS。在 Windows 上,用 VS 也是没问题的。

安装的时候,工作负载可以选“使用C++的桌面开发”,这个其实不选也可以的,老周已做过实验,不选这个也能编译。所以,可以在单个组件中安装以下各项:

1、C++核心功能;

2、C++ 2022 可再发行程序更新包;

3、MSBuild(这个装上好一点,不装也没报错);

4、MSVC 143 C++ 生成工具(这个是重点,要装,要装);

5、用于 Windows 的 CMake 工具(这个也必须装上);

6、Windows SDK 任选一个版本,建议越新越好(自己编译源代码时必须)。

7、其他的组件自己看心情。

如果你不用 VS,但在 Windows 上也要装 MSVC 生成工具。在 Windows 上还是建议用微软的编译器,不容易出现莫名其妙的错误。老周实验过,用 Windows 版的 g++ 编译失败。

当然本文讲的  VS Code,但如果是 Windows 平台,也要装 VS 生成工具的。

-----------------------------------------------------------------------------------------------------------------------

编译源代码

Qt 现在也开始装X了,编译好的内裤只支持在线安装,十有八九慢到你要装几天才能装好,而且体积比 VS 还要大几倍。想离线安装只能下载源代码自己编译。

编译源代码需要以下工具:

1、Windows SDK,否则会找不到相关 .lib 文件而出错。

2、Python,3.x 后随便找个版本。可以下载嵌入版,不用安装,解压后,把Python可执行文件所在的目录路径添加到 PATH 变量中。

3、Perl。可以下载绿色版压缩包,解压到某目录,将包含 perl.exe 的目录添加到 PATH 环境变量中,一般位于 <解压后目录>\Perl\perl\bin。

 

下载源码可以用国内镜像,如清华大学的:Index of /qt/archive/qt/ | 清华大学开源软件镜像站 | Tsinghua Open Source Mirror

最新的是 6.3,进去之后,不要下载整个源码包,而是找到 submodules 目录。核心组件是 qtbase-everywhere-6.xxx。

qtbase 是基础包,只编译这个模块的代码也能写 Qt 程序。解压之后,放在一个路径无空格无特殊符号的目录下,如 E:\SDK\Qt。然后执行一下 configure 脚本,Windows 上是有后缀 .bat 的,Linux 脚本无后缀。

命令行参数可参考帮助文档,实际上我们只关心一个参数 -prefix。这个参数指定在编译成功后,复制(安装)动态库的目录。因为编译时会产生许多后期没用的文件,所以才要指定这个路径。操作方法:

打开 “Visual Studio 2022” -- "x64 Native Tools Command Prompt for VS 2022"。

不要用 Developer Command Prompt for VS 2022,因为用这个你要指定 CPU 架构,若不指定默认编译出来的库是 32 位的。

【注意:下面输入命令这一大段,你先别着急跟着输入。请你先看完了再输入。因为这 Qt 6 在编译前的配置有些雷区。即在“+++++++++++”与“+++++++++++”之间这一大段内容】

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

先看最保险的操作,全按官方文档的来,基本保持默认。

打开 x64 Native Tools Command Prompt for VS 2022 工具的命令提示窗口,输入:

cd <源码路径> 
configure -prefix F:\Qt6\Libs

这样配置之后,将来在执行安装时会把生成的 .dll 复制到这个目录下。这厮好像重复执行会报错。老周一般是懒得去找错误,有时候就算找到错误在哪个 cmake 文件也解决不了问题,最直接有效的方法是全删掉,再从下载的压缩包里重新解压。官方文档说删除 CMakeCache.txt 文件可以,但老周尝试过,也是会报错的。

另外,如果打算将来要编译其他模块,并且让这些模块所生成的二进制文件减少调试符号,就要加上 -release 参数。

configure -prefix F:\Qt6\Libs -release

虽然 qtbase 模块默认是以 release 模式编译,但有些子模块默认是 debug 模式编译的。所以,如果希望后面编译的所有模块都以 release 模式编译,那就明确使用此参数。

一切顺利之后,直接交给 CMake 解决。编译:

cmake --build .

. 是源码所在目录,因为上面我们已经 cd 到源码目录了,所以这里用个“.”表示当前目录。

运气好的话,一次通过。这时候电脑的 CPU 风扇会发疯,请做好心理准备。因为只编译一个基础模块,所以花的时间会少一些。

编译成功后,还要执行一下安装操作:

cmake --install .

后面的“.”依然指的是当前目录(源码目录),编译后的二进制文件(重点是那些 .dll)会复制到你刚才用 -prefix 参数配置的路径下。如刚才配置的是 F:\Qt6\Libs。

上面的方案是保证出错概率最低的做法,但是,生成文件会和源码混在一起,想手动清理它们估计会累死人。如果想三个基本目录相互隔离,就要用接下来的方法。这三个目录是:

1、源码。

2、build 输出目录。

3、安装目录。

我们来假设一下:

1、源代码:G:\Kits\Qt6\src\qtbase

2、build 输出目录:G:\Kits\Qt6\build

3、安装目录:G:\Kits\Qt6\installed

其实,这些目录都在 G:\Kits\Qt6 下面。

废话一下,我现在的想法是:保留源代码目录不变,想留着将来重复用;把生成/编译输出的东东放在 build 目录,编译好后的二进制文件安装到 installed 目录。下面开始操作。

【警告:以下操作出现灵异事件的概率大,请鼓起勇气尝试。世事难料,各自珍重】

首先,打开 x64 Native Tools Command Prompt fo VS 20XX,定位到 G:\Kits\Qt6\build,这个路径要根据你实际的路径写。

cd /d G:\kits\Qt6\build

命令工具窗口当前目录一般是 C 盘,要跨分区 CD 的话,要加上 /d 参数。

保持 build 目录为当前目录不要改变,在 build 目录中执行 configure 脚本。

..\src\qtbase\configure -prefix ..\installed

老周这里用的是相对路径,你也可以用绝对路径。注意 -prefix 参数是一个短横线的,不能写成 --prefix,会出错。如果看到下面这一行,说明你运气好,第一关算是过了,接下来的编译成功率很高。

Build files have been written to: G:/Kits/Qt6/build

接下来的操作就和前面的一样了。保持当前目录在 build 不变,依次执行:

cmake --build .
cmake --install .

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

大约会编译 1700 多个目标。这过程中很有可能会出错退出。可以尝试重新执行 cmake --build . ,一般会成功的。 在 installed\bin 目录下你会看到许多 .dll,这说明一切顺利。

编译默认是生成动态库的,所以在 configure 时我们不用改。建议用动态库,若编译为静态库,做项目时会涉及授权问题,也就是说你要购买。

 

配置 VS Code

编译完毕后,就是配置 VS Code 了,其实就是安装插件罢了。这几个插件少不了:

1、C/C++(微软官方的)

2、CMake Tools(也是微软官方的)

3、CMake Language Support(有了这个,写CMake时有智能提示)

有以上这几个就够玩了。另外,微软有个集合包,叫做 C/C++ Extension Pack,会一次安装一堆 C++ 有关的插件。觉得有必要可以装装,觉得没必要就当它透明。

打开 VS Code 的设置页,找到扩展中的 CMake Tools,滚动到 Environment,点“添加项”设置一个环境变量。

PATH = G:\Kits\Qt6\installed;G:\Kits\Qt6\installed\bin;%PATH%

【键】是“PATH”,【值】是 = 后面那串。路径就是你刚才 Qt6 安装的目录,包括安装目录,以及安装目录下的 bin。

保存退出,收工。

 

开始装逼

 如果上面各步骤都成功,我们现在可以开写玩了。

在 VS Code 中打开一个目录作为工作区。然后按 【ctl + shift + P】,输入“cmake”,找到“CMake 配置”命令,执行。

 

 编译器选择 amd64 的,如果你要 32 位的就选 x86。

 

 【注】如果你要写 32 位的,那前面在编译源代码时也要编译一份 32 位的动态库。这个你懂的,32 位和 64 位的二进制文件是不同混用的。

 

这时,提示还没创建 CMakeLists.txt ,那就点创建呗。但是,生成的 CMakeLists.txt 文件中的东东很多不是我们所需要的。凡是有 enable_testing,CTest 什么的,全部干掉。   

大致内容如下:

cmake_minimum_required(VERSION 3.15.0)

# 项目名称
project(testApp LANGUAGES CXX)

# 设置变量
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)

# 引用需要的库
find_package(Qt6 REQUIRED COMPONENTS Core Widgets Gui)
# 添加源代码文件
add_executable(testApp WIN32 main.cpp)
# 与相关的库链接
target_link_libraries(testApp PRIVATE Qt6::Widgets Qt6::Core Qt6::Gui)

1

cmake_minimum_required(VERSION 3.15.0)
设置要使用的 CMake 最小版本号,这个你看情况写吧,我这里写 3.15。
 
2:设置项目的名称,这个也是自己定义的,比如你的项目叫 KillDog。
project(KillDog LANGUAGES CXX)
CXX 表示 C++ 语言。

3:设置变量。

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)

CMAKE_CXX_STANDARD = 17     C++版本号 ,不要低于17。

CMAKE_CXX_STANDARD_REQUIRED = on 或 yes 或 1,和上面一起,必须符合C++版本。

CMAKE_AUTOMOC = on 或 yes 或 1,这个在Qt 项目里一般要开启,允许一些独特语法转译为C++代码。说白了就是 Qt 里面的信号和槽,用到特定的语法(其实这些语法是用宏定义的)。

CMAKE_AUTOUIC = on 或 yes 或 1,这个如果用到了 uic 资源时才会开启,没用到就可以不写。

 

4:引入要使用的库,Qt6 中使用 find_package 命令,格式都是固定,官方文档中有,可以照着抄。

 

 

 

5:添加源代码文件。

add_executable(testApp WIN32 main.cpp)

第一个是目标名,一般和项目名称相同,你可以自己取名。接着 WIN32 不能少(仅限于 Windows),否则窗口出不来,只出来控制台。main.cpp是代码文件,有多个代码文件也要写上,比如 a.cpp b.cpp c.cpp,如果写漏了就导致有的文件没有被编译,那你的程序能运行起来才怪呢。

 

6:链接。把目标(上面 add_executable 就是为目标加了源文件)和库链接起来。

target_link_libraries(testApp PRIVATE Qt6::Widgets Qt6::Core Qt6::Gui)

  这个格式也是固定的,照着文档抄就行了。请看上面 find_package 的截图。

 

----------------------------------------------------------------------------------------------------------------------------------

下面是 main.cpp 中的代码,我们来试试前面的配置是否正确。                           ,

 

#include <QApplication>
#include <QWidget>
#include <QHBoxLayout>
#include <QPushButton>
int main(int argc, char** argv) 
{
// 这个 App 和 Widgets 在代码上不直接引用 // 但它是必须的,它会开启主消息循环 QApplication app(argc, argv); // 准备主窗口 QWidget window; // 窗口标题 window.setWindowTitle("穷屌丝应用程序"); // 设置窗口大小 window.resize(400, 300); // 控件 QPushButton *btn1 = new QPushButton("第一个按钮"); QPushButton *btn2 = new QPushButton("第二个按钮"); // 布局 QHBoxLayout *layout = new QHBoxLayout(&window); // 将控件放入布局中 layout -> addWidget(btn1, 2); layout -> addWidget(btn2, 1); // 显示窗口 window.show(); // 别忘了这一行,正式启动程序 return app.exec(); // 调用静态的也行 //return QApplication::exec(); }

QApplication 类用于启动应用程序的主消息循环,它不需要显式引用 Widget 对象。调用 exec 方法正式开始消息循环。这个方法会一直循环,直到应用程序退出(主窗口/根 Widget 被关闭)才会返回。若无错误,就返回 0 ,这个返回值可以直接沿着 main 函数返回。

注意,所有初始化(创建窗口,放置控件等)代码必须在 exec 方法之前调用。exec 方法一旦调用,除非应用程序退出,否则是不会返回的。所以不要在 exec 之后写任何代码(清理代码除外)。

QWidget 是众多 UI 元素/控件的基类,直接使用它可以作为应用程序的窗口——就是一个空白窗口。setWindowTitle 方法用来设置窗口标题栏上的文本;resize 方法调整窗口的大小;show 方法显示窗口。

QHBoxLayout 是一个布局类,用来布局窗口中控件的位置。它指的是 UI 元素沿水平方向排列。这个 Layout 类似于 WPF 中的 StackPanel。嗯,相信你也猜到,要垂直布局,就用 QVBoxLayout 类。如果想向 StackPanel 那样,可以通过设置来控制水平或垂直方向,可以用 QBoxLayout,通过 setDirection 方法可以设置:从左到右、从右到左、从上到下、从下到上。

QPushButton 就是常见的按钮。

在 Qt 应用程序中,new 出来的指针不一定要 delete / free 的。因为它有个引用树的概念,会自动释放指针所引用的东西。前提是这些对象是连接到 QObject 上的。比如窗口是 QWidget ,放在窗口内的控件元素如果以窗口为父对象,就像上面那个例子,里面的 QHBoxLayout、QPushButton 等,是连接到 QWidget 上的,所以不需要 delete 指针,它会自动释放。

我们 build 一下这个项目,然后运行它。

 

 注意看 VS Code 底部的状态栏,你能找到这两个按钮。

 

如果没有问题,就能看到应用程序窗口了。

 

 

在 Linux 上的编译和配置与 Windows 上差不多的。注意先安装 g++,选这个编译的话可避免各种灵异事件。老周在 Ubuntu 上试验时,曾经遇到过一次灵异事件,至今无法解释。编译 Qt6 源代码顺利完成,写一个 app 试了下也能运行起来。但是,系统重启后就进不了系统了,除了 root 帐户外,所有帐户都无权限登录。切换到 init 2 登录也不行,一登录就会被弹出来。就是除 root 外所有用户都没有任何权限,连登录的权限都没有。这现象无法解释,因为那次老周成功登入系统后只编译了 Qt6 源码,写了个测试 app,也没做别的事,重启后就挂了。

 

posted @ 2022-07-24 21:28  东邪独孤  阅读(2434)  评论(0编辑  收藏  举报