本文将使用CMake和Visual Studio构建一个Qt的HelloWorld程序,面向新手,旨在
给自己做个记录,省的以后忘了手把手教你使用相对系统和方便管理的方式构建一个自己的Qt项目,会详细展示从创建到打包发布的过程,最终你将拥有一个自己的HelloWorld程序安装包,并可以提供给别人在其他电脑上安装并使用。
如果你对此文中的操作有任何不清楚的地方或是过程中出现文章未提及的错误,欢迎留言。
另外由于本人很菜,难免有理解错误和显得小白的地方,还请各位大佬批评指正。
关于环境和工具
Windows7,Visual Studio 2017
Qt 5.10.1
Qt教程指路《Qt学习之路2》
CMake 3.17.1
CMake教程我自己没找到太好的,CMake本身功能非常强大,足以管理大型项目。我多是想用什么功能的时候针对某一点去百度或google,自己也在学习过程中,如果有好的教程资料欢迎推荐。
Git
非必须,但如果你还不了解,强烈推荐学习一下。
git教程指路
git bash可以让你在Windows下使用Linux风格的控制台和命令。
各个工具或软件的安装包和安装教程请自行寻找,这里就不多说了。
这里额外提一嘴,新手在跟教程学习的时候,还是要多注意环境问题。区别通常不大,但可能会引起一些奇奇怪怪的问题,尤其是各个软件有较大版本差异的时候。一致的环境有助于减少学习过程中出现令人一头雾水的问题,并且操作过程与教程图文相符也能降低学习开销,当然这只是在方便配置相同环境的前提下……
开始创建项目,编写代码文件
编写demomain.cpp,代码如下
1 2 3 4 5 6 7 8 9 10 11 12 | #include <QApplication> #include <iostream> #include "mainwindow.h" int main(int argc, char *argv[]) { QApplication app(argc,argv); MainWindow mainWindow; mainWindow.show(); std::cout << "in func main" << std::endl; return app.exec(); } |
Mainwindow.h代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | #ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> namespace Ui { class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = nullptr); ~MainWindow(); private: Ui::MainWindow *ui; }; #endif // MAINWINDOW_H |
MainWindow.cpp代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | #include "mainwindow.h" #include "ui_mainwindow.h" #include <iostream> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); } MainWindow::~MainWindow() { delete ui; } |
CMakeLists.txt如下
这里需要注意一下把 CMAKE_PREFIX_PATH变量的内容设置成你自己电脑中Qt的安装目录
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | cmake_minimum_required(VERSION 3.12.0) #set PROJECT_NAME and version project(HelloWorld) set(VERSION_MAJOR 0) set(VERSION_MINOR 0) set(VERSION_PATCH 1) #set path for QT set(CMAKE_PREFIX_PATH F:/QT/5.10.1/msvc2017_64) # Find includes in corresponding build directories set(CMAKE_INCLUDE_CURRENT_DIR ON) # Instruct CMake to run moc automatically when needed set(CMAKE_AUTOMOC ON) # Create code from a list of Qt designer ui files set(CMAKE_AUTOUIC ON) find_package(Qt5 REQUIRED COMPONENTS Core Widgets Gui) set(project_ui MainWindow.ui) set(project_headers MainWindow.h) set(project_sources demoMain.cpp MainWindow.cpp) add_executable(${PROJECT_NAME} ${project_headers} ${project_ui} ${project_sources}) # Use the widgets module from Qt 5 target_link_libraries(${PROJECT_NAME} PUBLIC Qt5::Core Qt5::Gui Qt5::Widgets) |
打开Qt Designer创建需要的Mainwindow.ui文件,保存至代码目录下
HelloWorld嘛,拖个label进来就好
开始构建
在源代码目录下使用git bash,并输入命令。我们这里使用外部构建,新建子目录build并进入build文件夹进行构建项目,这样做可以使构建生成的文件与源代码文件置于不同的目录下,便于管理,源代码目录清晰整洁,需要删除构建文件时直接删除build文件夹即可,这也是使用CMake的方便之处。也可以通过编写脚本或批处理文件执行更细致的处理,后面的文章会提及一部分这些内容。
这里使用Windows的控制台cmd进入相应目录执行亦可,但是就要使用Windows相应的命令了,与以下图片中的命令不完全相同。
执行完毕后,应该能在build目录内看到以下文件,这就是熟悉的Visual Studio的工程项目啦
打开HelloWorld.sln会启动Visual Studio,右键项目点击生成
构建过程中会出现的问题
首先注意在CMakeLists中我设置的Qt路径为
将VS生成目标程序改为x64即可,修改方法如下:
不过这个方法其实并不是非常可取,尤其我们是采用CMake构建项目的情况下,每次修改代码需要重新执行CMake的时候,VS的设置都会重置,需要重复执行上述步骤,不过也作为解决办法介绍下,通过修改CMakeLists.txt解决这个问题的方法后面再谈。
这里还可能遇到另一个错误:
constexpr 函数 “qCountLeadingZeroBits” 不会生成常数表达式
这里据说是使用msvc2017编译的一个bug,与Windows操作系统有关,可以通过修改一个Qt的头文件解决(替换前记得备份原文件,我觉得这是个好习惯)。方法指路
安装VS2017时默认安装的是Win10SDK,在我安装Win8.1SDK和Win7SDK后,即便不修改头文件,该错误也不再出现,原谅我没有删除SDK去确认问题是否与此有关……
得到可执行程序
如若上述步骤成功,在build/x64/Debug目录下应该会生成一个HelloWorld.exe。我们终于得到了自己的HelloWorld了!然后兴冲冲双击执行的时候,出现如下错误:
这是缺少依赖文件造成的,也许可以通过修改系统的环境变量使其包含Qt的安装目录来解决问题,但是不推荐这样做。修改环境变量可能造成其他问题,而且即便在本机解决了问题,当你把程序安装到其他电脑上时,还是会因为缺少依赖文件而无法运行。
添加依赖文件
正确的做法是将所需的依赖文件添加至可执行文件(即HelloWorld.exe)的目录下。但是所需文件不只一个,手动查找复制非常麻烦,其实Qt提供了一个命令用来解决此问题,此命令叫windeployqt
可以打开git bash按下图执行:
前面的命令用来添加临时环境变量,执行export和echo $PATH后可以看到windeployqt.exe所在的目录已经被添加进来。临时环境变量仅在当前控制台窗口生效,如果不添加环境变量会无法找到windeployqt命令。当然你也可以选择使用绝对路径来执行命令,这样就不必添加环境变量了。
注意: 要使用编译器对应目录下的windeployqt,如在CMakeLists.txt中我指定的编译器为
另外上述图片因git bash的关系使用的也是Linux的命令,如果使用Windows的cmd控制台请自行百度如何添加临时环境变量。
执行成功
执行完上述所有操作,我们就应该可以使用自己的HelloWorld程序了。
至此我们成功的制作了自己的Qt程序,但是这里有很多不方便的操作以及见招拆招但却感觉不是那么得体的解决问题的方法。我觉得把问题尽可能多的展现出来还是有利于对整个过程的理解,后面再加以补充完善。如何令我们的HelloWorld显得更像一个便于管理的项目,以及如何在此基础上增添程序功能,制作安装包等问题,会在之后的文章中具体阐述。