赞
踩
天下苦C++已久!各位C++开发者们,大家说什么是现在的C++最大的痛点?
是内存管理吗?
是散乱无章的标准库吗?
是隐藏的很多语言层面的陷阱吗?
都不是!C++目前的最大的痛点就是没有统一的包管理器!以及编译构建混乱!各种轮子到处飞,但是很多都安不到自己的项目上去!
本文将采用CLION平台,配合使用MINGW/MSVC编译器进行统一的包管理和对OPENCV以及QT库、Boost库的导入。我将以自己两天的踩坑精力为C++开发者们铺平道路。
本文主要以MINGW64为主,MSVC配置也是同理的。
目录
Qt的安装很简单,我们进入Qt官网
选择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的工具链
这里是我已经配置好的。
我们点击加号,选择工具链
我们配置好工具链之后,应用并退出。
这个时候其实就基本配置完毕了,开始写CMAKE
需要注意的是,QT CREATOR在项目里面set了很多变量,但是在CLION打开这个项目的时候我们是没有SET的。也就是说,这些变量需要我们自己去指定。
需要手动指定的变量
- MOC作用:
- moc 全称是 Meta-Object Compiler,也就是“元对象编译器”。Qt 程序在交由标准编译器编译之前,先要使用 moc 分析 C++ 源文件。如果它发现在一个头文件中包含了宏 Q_OBJECT,则会生成另外一个 C++ 源文件。这个源文件中包含了 Q_OBJECT 宏的实现代码。这个新的文件名字将会是原文件名前面加上 moc_ 构成。这个新的文件同样将进入编译系统,最终被链接到二进制代码中去。因此我们可以知道,这个新的文件不是“替换”掉旧的文件,而是与原文件一起参与编译。另外,我们还可以看出一点,moc 的执行是在预处理器之前。因为预处理器执行之后,Q_OBJECT 宏就不存在了。
- Qt 将源代码交给标准 C++ 编译器,如 gcc 之前,需要事先将这些扩展的语法去除掉。完成这一操作的就是 moc。
- cmake_minimum_required(VERSION 3.26)
-
- # 设置C++标准
- set(CMAKE_CXX_STANDARD 17)
-
- # 必须要求C++17
- set(CMAKE_CXX_STANDARD_REQUIRED ON)
- set(CMAKE_CXX_STANDARD_REQUIRED ON)
-
- # 设置QT的标准
- set(CMAKE_AUTOMOC ON)
- set(CMAKE_AUTORCC ON)
- set(CMAKE_AUTOUIC ON)
-
- # 设置QT_DIR,也可以写在环境变量里面
- set(QT_DIR D:/QT_6/6.7.1/mingw_64/lib/cmake)
-
- # 设置头文件和库搜索路径,这包含
- set(CMAKE_PREFIX_PATH
- #QT
- ${QT_DIR};
- )
-
- # 设置参与构建的文件
- set(PROJECT_FILES
- main.cpp
- )
-
- # 项目信息
- project(QT_VCPKG)
-
- # 查找Qt6库
- find_package(Qt6 COMPONENTS Core Gui Widgets REQUIRED)
-
- # 添加可执行文件
- add_executable(QT_VCPKG ${PROJECT_FILES})
-
- # 链接Qt6库
- target_link_libraries(QT_VCPKG PRIVATE Qt6::Core Qt6::Gui Qt6::Widgets)
运行一个简单的程序
- #include <QApplication>
- #include <QPushButton>
-
-
- int main(int argc, char *argv[]) {
- QApplication a(argc, argv);
- QPushButton button("Hello world!", nullptr);
- button.resize(200, 100);
- button.show();
-
- return QApplication::exec();
- }
如果窗口显示正常,那么一切大吉。如果出现错误退出,请看看工作目录有没有选上。
把工作目录直接设置为QT的目录可以解决99%的QT库链接失败问题。
Designer就是QT的用来拖拽和设置控件的编辑窗口。
UIC就是把UI文件转换成C文件,也就是一个.h文件。总所周知,QT WIDGET最好的开发方式就是用代码来写。但是UIC有一个比较大的问题就是,用designer的.ui文件,一旦生成之后再次修改,你自己在这个.h文件中的修改会全部消失。
所以,最好的方式就是,在designer里面对窗口进行设置。
将.qrc资源文件编译成二进制文件
RCCh(建议配置)
将.qrc资源文件转换为.h文件
我们点开外部工具
我们对这些工具进行如下设置
我们点击clion,上面自带一个vcpkg
如果没有,那它一定在这里
点开之后,我们新建一个,自己在里面新建一个目录,最好放在D盘,然后自动下载。
下载完毕如下
这里我们选择经典模式,我们有两种选择
比如我这里,配置了三个VCPKG,大家可以按照我的设置。我使用的是x64-mingw-dynamic,那么在经典模式下它就会默认安装这个。当然还有x64-windows,等等版本,请在VCPKG文档中自行检索。
CMake也是同理
- # 设置VCPKG的工具链文件和目标triplet
- set(CMAKE_TOOLCHAIN_FILE "D:/vcpkg/scripts/buildsystems/vcpkg.cmake")
- set(VCPKG_TARGET_TRIPLET "x64-mingw-dynamic")
我们在CMAKE中设置好工具链,就可以不用手动设置搜索目录了,使用VCPKG进行包管理(经典模式下),我们只需要进行两个操作(动态引入)
下面是一个案例
- # 查找fmt库
- find_package(fmt CONFIG REQUIRED)
-
- # 添加可执行文件
- add_executable(QT_VCPKG ${PROJECT_FILES})
-
-
- # 链接fmt库
- target_link_libraries(QT_VCPKG PRIVATE fmt::fmt)
假设我们有一个QT,不好用VCPKG做管理,那我们需要自己写CMAKE,关于QT的CMake我们写在了上面,接下来我来说说怎么在这个场景下引入OPENCV包。
关于如何用编译OPENCV,可以参考这篇文章
编译之后记得将用户环境变量设置好
我们需要写好这两个环境变量,这样使用就很方便了。使用什么平台的编译器,就要使用什么版本的编译文件。
然后是系统的环境变量(下面的那一个)
如此一来,OPENCV就配置好了。
然后我们需要添加OPENCV,就需要添加以下到CMakeLists中去。
- # 设置头文件和库搜索路径
- set(CMAKE_PREFIX_PATH
- ${QT_DIR};
- ${OPENCV_DIR};
- )
-
-
- # 查找opencv库
- find_package(OpenCV REQUIRED)
-
- add_executable(...)
-
- # 链接Opencv库
- target_link_libraries(${PROJECT_NAME} PRIVATE ${OpenCV_LIBS})
如此一来,我们只需要设置一个搜索路径,找包,然后在后面动态链接即可,也并没有特别麻烦。
比如我们下一个fmt的包,我这里是MINGW64-dynamic版本。(fmt也可以无库,纯头文件来引入)
- # 设置VCPKG的工具链文件和目标triplet
- set(CMAKE_TOOLCHAIN_FILE "D:/vcpkg/scripts/buildsystems/vcpkg.cmake")
- set(VCPKG_TARGET_TRIPLET "x64-mingw-dynamic")
-
- # 查找fmt库
- find_package(fmt CONFIG REQUIRED)
-
- add_executable(...)
-
- # 链接fmt库
- target_link_libraries(QT_VCPKG PRIVATE fmt::fmt)
然后我们写一个文件测试一下
- #include<fmt/core.h>
-
- int main(){
- std::string s="hello cmx";
- fmt::print(s);
- }
只要不出现错误代码退出就是库链接正常了,就OK了,一个函数能用就是整个库都能用。
当VCPKG不支持下载的时候,比如MINGW64的windows平台不支持BOOST库的某些组件,下载出现失败,会出现提示:用git pull升级VCPKG版本。
实际上,根本不是VCPKG的版本问题,而是有些代码仓库没有这个版本。
这个时候怎么做呢?我们换一个版本,比如静态编译版本。
比如大名鼎鼎的Boost::Asio模块,其实MINGW64没有dynamic版本,我们只需要下载static版本即可。
然后就是传统的静态链接,在add_executable之前添加即可
- # 静态链接boost::Asio库
- include_directories(D:/vcpkg/packages/boost-asio_x64-mingw-static/include)
- # 通过手动添加一些windows下的socket库来使用Asio库
- link_libraries(libgdi32.a libwsock32.a libws2_32.a)
注意asio是没有动态库的,它其实是需要winsock的库,但是没有提供库的文件。这里写链接winsock也行。
我写了一个代码,用于给大家做一个测试,看看自己的包安装的是否到位了,环境是否配置好了。
这是CMAKE
- #############------------- 本CMakeLists适用于QT-MINGW-64的搭建,请选择构建CMake应用的时候将Qt的mingw64下的bin文件夹添加进工作目录 -------------#############
-
- cmake_minimum_required(VERSION 3.26)
-
- # 设置C++标准
- set(CMAKE_CXX_STANDARD 17)
-
- # 必须要求C++17
- set(CMAKE_CXX_STANDARD_REQUIRED ON)
- set(CMAKE_CXX_STANDARD_REQUIRED ON)
-
- # 设置QT的标准
- set(CMAKE_AUTOMOC ON)
- set(CMAKE_AUTORCC ON)
- set(CMAKE_AUTOUIC ON)
-
- # 设置QT_DIR,也可以写在环境变量里面
- set(QT_DIR D:/QT_6/6.7.1/mingw_64/lib/cmake)
-
- # 设置VCPKG的工具链文件和目标triplet
- set(CMAKE_TOOLCHAIN_FILE "D:/vcpkg/scripts/buildsystems/vcpkg.cmake")
- set(VCPKG_TARGET_TRIPLET "x64-mingw-dynamic")
-
- # 设置头文件和库搜索路径,这包含
- set(CMAKE_PREFIX_PATH
- #QT
- ${QT_DIR};
- #OPENCV
- ${OPENCV_DIR};
- )
-
- # 设置参与构建的文件
- set(PROJECT_FILES
- main.cpp
- )
-
- # 项目信息
- project(QT_VCPKG)
-
- # 查找fmt库
- find_package(fmt CONFIG REQUIRED)
-
- # 查找Boost库,指定需要的组件
- find_package(Boost REQUIRED COMPONENTS thread chrono )
-
- # 查找Qt6库
- find_package(Qt6 COMPONENTS Core Gui Widgets REQUIRED)
-
- # 查找opencv库
- find_package(OpenCV REQUIRED)
-
- # 静态链接boost::Asio库
- include_directories(D:/vcpkg/packages/boost-asio_x64-mingw-static/include)
- # 通过手动添加一些windows下的socket库来使用Asio库
- link_libraries(libgdi32.a libwsock32.a libws2_32.a)
-
- # 添加可执行文件
- add_executable(QT_VCPKG ${PROJECT_FILES})
-
- # 链接Qt6库
- target_link_libraries(QT_VCPKG PRIVATE Qt6::Core Qt6::Gui Qt6::Widgets)
-
- # 链接fmt库
- target_link_libraries(QT_VCPKG PRIVATE fmt::fmt)
-
- # 链接Boost库
- target_link_libraries(QT_VCPKG PRIVATE Boost::thread Boost::chrono)
-
- # 链接Opencv库
- target_link_libraries(${PROJECT_NAME} PRIVATE ${OpenCV_LIBS})
这是主函数,
注意自己手动修改一下图片的路径
- #include "boost/thread.hpp"
- #include <QApplication>
- #include <QPushButton>
- #include <boost/asio.hpp>
- #include <fmt/core.h>
- #include <opencv2/opencv.hpp>
- #include <iostream>
-
- // 使用 Boost.Asio 进行异步操作
- void async_task(boost::asio::io_service& io_service) {
- boost::asio::steady_timer timer(io_service, boost::asio::chrono::seconds(2));
- timer.wait();
- std::cout << "Async task completed." << std::endl;
- }
-
- // 使用 Boost 线程库创建线程
- void thread_task() {
- std::cout << "Thread task started." << std::endl;
- boost::this_thread::sleep_for(boost::chrono::seconds(1));
- std::cout << "Thread task completed." << std::endl;
- }
-
- // 使用 OpenCV 进行图像处理
- void process_image() {
- std::string input_path = "D:/OPENCV_VCPKG/shen.jpg";
- std::string output_path = "D:/OPENCV_VCPKG/processed_image.jpg";
- cv::Mat image = cv::imread(input_path, cv::IMREAD_COLOR);
- if (image.empty()) {
- std::cerr << "Error opening image!" << std::endl;
- return;
- }
- cv::cvtColor(image, image, cv::COLOR_BGR2GRAY);
- cv::imwrite(output_path, image);
- std::cout << "Image processed and saved as " << output_path << "." << std::endl;
- }
-
-
- int main(int argc, char *argv[]) {
- // 创建一个新的线程来运行线程任务
- boost::thread t(thread_task);
-
- // 使用 Boost.Asio 进行异步操作
- boost::asio::io_service io_service;
- boost::asio::io_service::work work(io_service);
- boost::thread asio_thread(boost::bind(&boost::asio::io_service::run, &io_service));
- io_service.post(boost::bind(async_task, boost::ref(io_service)));
-
- // 启动 Qt 应用程序
- QApplication app(argc, argv);
- QPushButton button("Hello, World!");
- QObject::connect(&button, &QPushButton::clicked, &app, &QApplication::quit);
- button.show();
-
- // 使用 fmt 库格式化字符串并输出
- std::string formatted_string = fmt::format("This is a formatted number: {}", 42);
- std::cout << formatted_string << std::endl;
-
- // 使用 OpenCV 进行图像处理
- process_image();
-
- // 等待 Boost 线程完成
- t.join();
- io_service.stop();
- asio_thread.join();
-
- return app.exec();
- }
如此,我们便自行配置了一个相当丰富的库的工作环境。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。