当前位置:   article > 正文

史上最全之一站式配置之WINDOWS下建立Qt+OPENCV+VCPKG+CLION+MINGW/MSVC的攻略_clion mingw与vcpkg怎么配置

clion mingw与vcpkg怎么配置

天下苦C++已久!各位C++开发者们,大家说什么是现在的C++最大的痛点?

内存管理吗?

是散乱无章的标准库吗?

是隐藏的很多语言层面的陷阱吗?

都不是!C++目前的最大的痛点就是没有统一的包管理器!以及编译构建混乱!各种轮子到处飞,但是很多都安不到自己的项目上去!

本文将采用CLION平台,配合使用MINGW/MSVC编译器进行统一的包管理和对OPENCV以及QT库、Boost库的导入。我将以自己两天的踩坑精力为C++开发者们铺平道路。

本文主要以MINGW64为主,MSVC配置也是同理的。

目录

一.Qt环境准备

CLION-QT配置

CLION-QT的CMAKE测试

在CLION上面配置QT的工具

Designer(最重要的,一定要配置)

UIC(最重要的,一定要配置)

RCCBinary(建议配置)

二.VCPKG环境准备

不同环境的选择

CMake的设置

三.导入包进行测试

不使用vcpkg的场景

自行管理OPENCV

使用vcpkg的场景

使用vcpkg管理fmt包

VCPKG不支持下载的场景

使用VCKPG+CMAKE静态链接

四.最终的测试


一.Qt环境准备

Qt的安装很简单,我们进入Qt官网

Qt Documentation | Home

选择download QT,然后根据自己的系统版本进行选择。

我们得到一个在线下载器

注册好账号进行登录

注意将QT放入到D盘下下载,因为体积比较大。

注意,比如在QT6.7.1中,你可以不勾选web assembly等一些工具,因为可能不太用得到,编译器有三种选择,MINGW,MSVC和LLVM。LLVM构建更加复杂,我的建议是下载MINGW64,当然了,如果你想利用VS搭建这个环境,采用VS+MSBUILD或者是VS+CMAKE的方式,你也可以选择MSVC。

  • MSVC:是WINDOWS下的最强大的编译器,对C++提供最新支持,但是它不能跨平台
  • MINGW:GNU的WINDOWS版本,可以在所有平台上运行,但是在windows上面构建比较麻烦,一些小的第三方的windows库可能不兼容mingw
  • LLVM:性能很好,但是构建比较麻烦,尤其是在WIN平台上构建起来比MINGW还要复杂得多。不建议使用。

勾选上这些之后,我们开始下载,然后我们可以发现一个qt creator,这是一个QT自带的IDE工具。如果桌面上没有,就先在第一次下载完成之后启动,先固定到任务栏,然后再去寻找QT CREATOR的快捷方式。

至此为止,WINDOWS上面的QT环境算是搭好了,但是这还不够。因为有的人,比如我,不喜欢QT designer的界面风格,也不会把它当做自己的主要生产力工具,所以,我们选择CLION。

关于怎么在VS上部署QT的,可以参考别的文章。在VS2022这一系列的平台上部署QT环境比在CLION上其实要简单的多,这里就不多赘述。这里就贴一个链接。

VS2022+QT开发环境搭建_vs2022 qt-CSDN博客


然后我们打开CLION,配置一下Qt的工具链

CLION-QT配置

我们先设置一下CLION的QT的工具链

这里是我已经配置好的。

我们点击加号,选择工具链

我们配置好工具链之后,应用并退出。

这个时候其实就基本配置完毕了,开始写CMAKE


CLION-QT的CMAKE测试

需要注意的是,QT CREATOR在项目里面set了很多变量,但是在CLION打开这个项目的时候我们是没有SET的。也就是说,这些变量需要我们自己去指定。

需要手动指定的变量

  • CMAKE_CXX_STANDARD:C++标准版本,最好直接指定为17,不然容易出错
  • QT_DIR:QT的不同编译器的CMAKE目录,自己指定
    • 如果想在生成不同编译器的项目,可以这么写CMAKE
      • if-else-endif ,在if的括号里面写上编译器名字,比如if(MSVC),然后写上对应的操作,然后用endif结束这个if语句。
  • CMAKE_AUTOMOC:自动MOC
    • MOC作用:
      • moc 全称是 Meta-Object Compiler,也就是“元对象编译器”。Qt 程序在交由标准编译器编译之前,先要使用 moc 分析 C++ 源文件。如果它发现在一个头文件中包含了宏 Q_OBJECT,则会生成另外一个 C++ 源文件。这个源文件中包含了 Q_OBJECT 宏的实现代码。这个新的文件名字将会是原文件名前面加上 moc_ 构成。这个新的文件同样将进入编译系统,最终被链接到二进制代码中去。因此我们可以知道,这个新的文件不是“替换”掉旧的文件,而是与原文件一起参与编译。另外,我们还可以看出一点,moc 的执行是在预处理器之前。因为预处理器执行之后,Q_OBJECT 宏就不存在了
      • Qt 将源代码交给标准 C++ 编译器,如 gcc 之前,需要事先将这些扩展的语法去除掉。完成这一操作的就是 moc。
  • CMAKE_AUTORCC:自动将图片和视频文件(qrc资源文件)转换为二进制资源文件
  • CMAKE_AUTOUIC:将.ui文件自动转换为一个.h的头文件,这是非常重要的一个工具
  • CMAKE_PREFIX_PATH:我们将QT的DIR,也就是QT_DIR转义输入即可,这是一个头文件和库文件的搜索路径。
  1. cmake_minimum_required(VERSION 3.26)
  2. # 设置C++标准
  3. set(CMAKE_CXX_STANDARD 17)
  4. # 必须要求C++17
  5. set(CMAKE_CXX_STANDARD_REQUIRED ON)
  6. set(CMAKE_CXX_STANDARD_REQUIRED ON)
  7. # 设置QT的标准
  8. set(CMAKE_AUTOMOC ON)
  9. set(CMAKE_AUTORCC ON)
  10. set(CMAKE_AUTOUIC ON)
  11. # 设置QT_DIR,也可以写在环境变量里面
  12. set(QT_DIR D:/QT_6/6.7.1/mingw_64/lib/cmake)
  13. # 设置头文件和库搜索路径,这包含
  14. set(CMAKE_PREFIX_PATH
  15. #QT
  16. ${QT_DIR};
  17. )
  18. # 设置参与构建的文件
  19. set(PROJECT_FILES
  20. main.cpp
  21. )
  22. # 项目信息
  23. project(QT_VCPKG)
  24. # 查找Qt6库
  25. find_package(Qt6 COMPONENTS Core Gui Widgets REQUIRED)
  26. # 添加可执行文件
  27. add_executable(QT_VCPKG ${PROJECT_FILES})
  28. # 链接Qt6库
  29. target_link_libraries(QT_VCPKG PRIVATE Qt6::Core Qt6::Gui Qt6::Widgets)

运行一个简单的程序

  1. #include <QApplication>
  2. #include <QPushButton>
  3. int main(int argc, char *argv[]) {
  4. QApplication a(argc, argv);
  5. QPushButton button("Hello world!", nullptr);
  6. button.resize(200, 100);
  7. button.show();
  8. return QApplication::exec();
  9. }

如果窗口显示正常,那么一切大吉。如果出现错误退出,请看看工作目录有没有选上。

把工作目录直接设置为QT的目录可以解决99%的QT库链接失败问题。


在CLION上面配置QT的工具

Designer(最重要的,一定要配置)

Designer就是QT的用来拖拽和设置控件的编辑窗口。

UIC(最重要的,一定要配置)

UIC就是把UI文件转换成C文件,也就是一个.h文件。总所周知,QT WIDGET最好的开发方式就是用代码来写。但是UIC有一个比较大的问题就是,用designer的.ui文件,一旦生成之后再次修改,你自己在这个.h文件中的修改会全部消失

所以,最好的方式就是,在designer里面对窗口进行设置。

RCCBinary(建议配置)

将.qrc资源文件编译成二进制文件

RCCh(建议配置)

将.qrc资源文件转换为.h文件


我们点开外部工具

我们对这些工具进行如下设置


二.VCPKG环境准备

我们点击clion,上面自带一个vcpkg

如果没有,那它一定在这里

点开之后,我们新建一个,自己在里面新建一个目录,最好放在D盘,然后自动下载。

下载完毕如下


不同环境的选择

这里我们选择经典模式,我们有两种选择

  • 手动指定下载的版本
  • 在环境变量或者CMAKE中进行设置

比如我这里,配置了三个VCPKG,大家可以按照我的设置。我使用的是x64-mingw-dynamic,那么在经典模式下它就会默认安装这个。当然还有x64-windows,等等版本,请在VCPKG文档中自行检索。

三元组参考 | Microsoft Learn


CMake的设置

CMake也是同理

  1. # 设置VCPKG的工具链文件和目标triplet
  2. set(CMAKE_TOOLCHAIN_FILE "D:/vcpkg/scripts/buildsystems/vcpkg.cmake")
  3. set(VCPKG_TARGET_TRIPLET "x64-mingw-dynamic")

我们在CMAKE中设置好工具链,就可以不用手动设置搜索目录了,使用VCPKG进行包管理(经典模式下),我们只需要进行两个操作(动态引入)

  1. 在add_executable()之前使用find_package()
  2. 在add_executable()之后使用target_link_libraries()

下面是一个案例

  1. # 查找fmt库
  2. find_package(fmt CONFIG REQUIRED)
  3. # 添加可执行文件
  4. add_executable(QT_VCPKG ${PROJECT_FILES})
  5. # 链接fmt库
  6. target_link_libraries(QT_VCPKG PRIVATE fmt::fmt)

三.导入包进行测试

不使用vcpkg的场景

自行管理OPENCV

假设我们有一个QT,不好用VCPKG做管理,那我们需要自己写CMAKE,关于QT的CMake我们写在了上面,接下来我来说说怎么在这个场景下引入OPENCV包。

关于如何用编译OPENCV,可以参考这篇文章

Windows下Visual Studio 编译OpenCV详细教程(win10+vs2017+opencv4.5.2)(OpenCV最新版)(特别适合无法科学上网的童鞋们)_windows环境下vsstudio编译opencv-CSDN博客

编译之后记得将用户环境变量设置好

我们需要写好这两个环境变量,这样使用就很方便了。使用什么平台的编译器,就要使用什么版本的编译文件。

然后是系统的环境变量(下面的那一个)

如此一来,OPENCV就配置好了。

然后我们需要添加OPENCV,就需要添加以下到CMakeLists中去。

  1. # 设置头文件和库搜索路径
  2. set(CMAKE_PREFIX_PATH
  3. ${QT_DIR};
  4. ${OPENCV_DIR};
  5. )
  6. # 查找opencv库
  7. find_package(OpenCV REQUIRED)
  8. add_executable(...)
  9. # 链接Opencv库
  10. target_link_libraries(${PROJECT_NAME} PRIVATE ${OpenCV_LIBS})

如此一来,我们只需要设置一个搜索路径,找包,然后在后面动态链接即可,也并没有特别麻烦。


使用vcpkg的场景

使用vcpkg管理fmt包

比如我们下一个fmt的包,我这里是MINGW64-dynamic版本。(fmt也可以无库,纯头文件来引入)

  1. # 设置VCPKG的工具链文件和目标triplet
  2. set(CMAKE_TOOLCHAIN_FILE "D:/vcpkg/scripts/buildsystems/vcpkg.cmake")
  3. set(VCPKG_TARGET_TRIPLET "x64-mingw-dynamic")
  4. # 查找fmt库
  5. find_package(fmt CONFIG REQUIRED)
  6. add_executable(...)
  7. # 链接fmt库
  8. target_link_libraries(QT_VCPKG PRIVATE fmt::fmt)

然后我们写一个文件测试一下

  1. #include<fmt/core.h>
  2. int main(){
  3. std::string s="hello cmx";
  4. fmt::print(s);
  5. }

只要不出现错误代码退出就是库链接正常了,就OK了,一个函数能用就是整个库都能用。


VCPKG不支持下载的场景

当VCPKG不支持下载的时候,比如MINGW64的windows平台不支持BOOST库的某些组件,下载出现失败,会出现提示:用git pull升级VCPKG版本。

实际上,根本不是VCPKG的版本问题,而是有些代码仓库没有这个版本。

这个时候怎么做呢?我们换一个版本,比如静态编译版本。

使用VCKPG+CMAKE静态链接

比如大名鼎鼎的Boost::Asio模块,其实MINGW64没有dynamic版本,我们只需要下载static版本即可。

然后就是传统的静态链接,在add_executable之前添加即可

  1. # 静态链接boost::Asio库
  2. include_directories(D:/vcpkg/packages/boost-asio_x64-mingw-static/include)
  3. # 通过手动添加一些windows下的socket库来使用Asio库
  4. link_libraries(libgdi32.a libwsock32.a libws2_32.a)

注意asio是没有动态库的,它其实是需要winsock的库,但是没有提供库的文件。这里写链接winsock也行。


四.最终的环境测试

我写了一个代码,用于给大家做一个测试,看看自己的包安装的是否到位了,环境是否配置好了。

这是CMAKE

  1. #############------------- 本CMakeLists适用于QT-MINGW-64的搭建,请选择构建CMake应用的时候将Qt的mingw64下的bin文件夹添加进工作目录 -------------#############
  2. cmake_minimum_required(VERSION 3.26)
  3. # 设置C++标准
  4. set(CMAKE_CXX_STANDARD 17)
  5. # 必须要求C++17
  6. set(CMAKE_CXX_STANDARD_REQUIRED ON)
  7. set(CMAKE_CXX_STANDARD_REQUIRED ON)
  8. # 设置QT的标准
  9. set(CMAKE_AUTOMOC ON)
  10. set(CMAKE_AUTORCC ON)
  11. set(CMAKE_AUTOUIC ON)
  12. # 设置QT_DIR,也可以写在环境变量里面
  13. set(QT_DIR D:/QT_6/6.7.1/mingw_64/lib/cmake)
  14. # 设置VCPKG的工具链文件和目标triplet
  15. set(CMAKE_TOOLCHAIN_FILE "D:/vcpkg/scripts/buildsystems/vcpkg.cmake")
  16. set(VCPKG_TARGET_TRIPLET "x64-mingw-dynamic")
  17. # 设置头文件和库搜索路径,这包含
  18. set(CMAKE_PREFIX_PATH
  19. #QT
  20. ${QT_DIR};
  21. #OPENCV
  22. ${OPENCV_DIR};
  23. )
  24. # 设置参与构建的文件
  25. set(PROJECT_FILES
  26. main.cpp
  27. )
  28. # 项目信息
  29. project(QT_VCPKG)
  30. # 查找fmt库
  31. find_package(fmt CONFIG REQUIRED)
  32. # 查找Boost库,指定需要的组件
  33. find_package(Boost REQUIRED COMPONENTS thread chrono )
  34. # 查找Qt6库
  35. find_package(Qt6 COMPONENTS Core Gui Widgets REQUIRED)
  36. # 查找opencv库
  37. find_package(OpenCV REQUIRED)
  38. # 静态链接boost::Asio库
  39. include_directories(D:/vcpkg/packages/boost-asio_x64-mingw-static/include)
  40. # 通过手动添加一些windows下的socket库来使用Asio库
  41. link_libraries(libgdi32.a libwsock32.a libws2_32.a)
  42. # 添加可执行文件
  43. add_executable(QT_VCPKG ${PROJECT_FILES})
  44. # 链接Qt6库
  45. target_link_libraries(QT_VCPKG PRIVATE Qt6::Core Qt6::Gui Qt6::Widgets)
  46. # 链接fmt库
  47. target_link_libraries(QT_VCPKG PRIVATE fmt::fmt)
  48. # 链接Boost库
  49. target_link_libraries(QT_VCPKG PRIVATE Boost::thread Boost::chrono)
  50. # 链接Opencv库
  51. target_link_libraries(${PROJECT_NAME} PRIVATE ${OpenCV_LIBS})

这是主函数,注意自己手动修改一下图片的路径

  1. #include "boost/thread.hpp"
  2. #include <QApplication>
  3. #include <QPushButton>
  4. #include <boost/asio.hpp>
  5. #include <fmt/core.h>
  6. #include <opencv2/opencv.hpp>
  7. #include <iostream>
  8. // 使用 Boost.Asio 进行异步操作
  9. void async_task(boost::asio::io_service& io_service) {
  10. boost::asio::steady_timer timer(io_service, boost::asio::chrono::seconds(2));
  11. timer.wait();
  12. std::cout << "Async task completed." << std::endl;
  13. }
  14. // 使用 Boost 线程库创建线程
  15. void thread_task() {
  16. std::cout << "Thread task started." << std::endl;
  17. boost::this_thread::sleep_for(boost::chrono::seconds(1));
  18. std::cout << "Thread task completed." << std::endl;
  19. }
  20. // 使用 OpenCV 进行图像处理
  21. void process_image() {
  22. std::string input_path = "D:/OPENCV_VCPKG/shen.jpg";
  23. std::string output_path = "D:/OPENCV_VCPKG/processed_image.jpg";
  24. cv::Mat image = cv::imread(input_path, cv::IMREAD_COLOR);
  25. if (image.empty()) {
  26. std::cerr << "Error opening image!" << std::endl;
  27. return;
  28. }
  29. cv::cvtColor(image, image, cv::COLOR_BGR2GRAY);
  30. cv::imwrite(output_path, image);
  31. std::cout << "Image processed and saved as " << output_path << "." << std::endl;
  32. }
  33. int main(int argc, char *argv[]) {
  34. // 创建一个新的线程来运行线程任务
  35. boost::thread t(thread_task);
  36. // 使用 Boost.Asio 进行异步操作
  37. boost::asio::io_service io_service;
  38. boost::asio::io_service::work work(io_service);
  39. boost::thread asio_thread(boost::bind(&boost::asio::io_service::run, &io_service));
  40. io_service.post(boost::bind(async_task, boost::ref(io_service)));
  41. // 启动 Qt 应用程序
  42. QApplication app(argc, argv);
  43. QPushButton button("Hello, World!");
  44. QObject::connect(&button, &QPushButton::clicked, &app, &QApplication::quit);
  45. button.show();
  46. // 使用 fmt 库格式化字符串并输出
  47. std::string formatted_string = fmt::format("This is a formatted number: {}", 42);
  48. std::cout << formatted_string << std::endl;
  49. // 使用 OpenCV 进行图像处理
  50. process_image();
  51. // 等待 Boost 线程完成
  52. t.join();
  53. io_service.stop();
  54. asio_thread.join();
  55. return app.exec();
  56. }

如此,我们便自行配置了一个相当丰富的库的工作环境。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/894808
推荐阅读
相关标签
  

闽ICP备14008679号