QtCreator、Visual Studio使用CMake与Vcpkg集成
基于c/c++的运行时库MT、MTd、MD、MDd的多样性的以及涉及到相关复杂的第三方库依赖,有过一次项目引用openssl的痛苦经历;另外还会涉及到平台相关的arm-uwp arm64-windows x64-linux x64-osx x64-uwp x64-windows-static x64-windows x86-windows等配置起来相对繁琐且容易出错,最为头疼的是会牵扯一些运行时错误;主要原因也是使用过很长一段时间的C#,那么c/c++是否也有和c#、python、java等语言一样的包管理软件呢,推荐使用vcpkg - Open source C/C++ dependency manager from Microsoft,关于更多的TRIPLET可以通过
vcpkg help triplet
查看
平台工具链
Windows10、Qt5.12.12、Visual Studio 2017、Visual Studio 2022、CMake 3.24.0、git 2.36.1.windows.1
工具安装与部署
-
Vcpkg
vcpkg.exe integrate install Applied user-wide integration for this vcpkg root. CMake projects should use: "-DCMAKE_TOOLCHAIN_FILE=D:/vcpkg/scripts/buildsystems/vcpkg.cmake"All MSBuild C++ projects can now #include any installed libraries. Linking will be handled automatically. Installing new libraries will make them instantly available. 设置系统环境变量
CMAKE_TOOLCHAIN_FILE
为D:/vcpkg/scripts/buildsystems/vcpkg.cmake
-
安装Visual Studio 2017/2022、CMake,安装2017的目的是提供给Qt MSVC
-
使用Vcpkg安装Boost、log4cplus、fmt来验证集成效果
vcpkg install boost:x86-windows boost:x64-windows fmt:x86-windows fmt:x64-windows log4cplus[core,unicode]:x86-windows log4cplus[core,unicode]:x64-windows ...... The package fmt provides CMake targets: find_package(fmt CONFIG REQUIRED) target_link_libraries(main PRIVATE fmt::fmt) # Or use the header-only version find_package(fmt CONFIG REQUIRED) target_link_libraries(main PRIVATE fmt::fmt-header-only) log4cplus provides CMake targets: # this is heuristically generated, and may not be correct find_package(log4cplus CONFIG REQUIRED) target_link_libraries(main PRIVATE log4cplus::log4cplus) -
这边的Vcpkg配置使用基于MSVC的Triplet所以使用Qt创建的工程使用MSVC 2017来进行创建,工程创建后
CMakeLists.txt
内容如下cmake_minimum_required(VERSION 3.14) project(IntegrateVcpkgWithCmake LANGUAGES CXX) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_AUTOUIC ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED ON) find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED) find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core REQUIRED) add_executable(IntegrateVcpkgWithCmake main.cpp) target_link_libraries(IntegrateVcpkgWithCmake Qt${QT_VERSION_MAJOR}::Core) -
接下来添加
fmt
、boost
、log4cplus
并应用起来-
编辑CMakeLists.txt如下
cmake_minimum_required(VERSION 3.14) project(IntegrateVcpkgWithCmake LANGUAGES CXX) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_AUTOUIC ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) # 设置头文件与源文件 file(GLOB INCLUDES *.h *.hpp) file(GLOB SOURCES *.c *.cpp *.cxx) # 设置头文件、源文件在IDE中的节点 source_group("INCLUDES" FILES ${INCLUDES}) source_group("SOURCES" FILES ${SOURCES}) # 开启c++17支持 set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED) find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core REQUIRED) # 引入QNetwork验证 find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Network REQUIRED) # 引入QWidgets验证 find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Widgets REQUIRED) # 引入fmt验证 find_package(fmt CONFIG REQUIRED) # 引入log4cplus作为日志模块 find_package(log4cplus CONFIG REQUIRED) # 引入boost验证 find_package(Boost REQUIRED) add_executable(IntegrateVcpkgWithCmake ${INCLUDES} ${SOURCES} ) # 连接设置 target_link_libraries(IntegrateVcpkgWithCmake PRIVATE fmt::fmt PRIVATE log4cplus::log4cplus Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Widgets Qt${QT_VERSION_MAJOR}::Network )
-
在QtCreator中编译运行
-
基于log4cplus的日志模块部分是先前写好,在这里可以作为验证使用,关于log4cplus是如何使用的这里就不做多余的介绍了,下面给出Logger的实现
-
Logger.h
#ifndef LOGGER_H #define LOGGER_H #include <iostream> #include <log4cplus/loggingmacros.h> #include <log4cplus/logger.h> #include <log4cplus/consoleappender.h> #include <log4cplus/fileappender.h> #include <log4cplus/layout.h> #include <log4cplus/helpers/loglog.h> #include <log4cplus/helpers/stringhelper.h> #include <log4cplus/helpers/property.h> #include <boost/shared_ptr.hpp> class Logger { public: static boost::shared_ptr<Logger> getInstance() { std::call_once(of, [&]() { instance = boost::shared_ptr<Logger>(new Logger()); }); return instance; } // static std::shared_ptr<Logger> getInstance() { // std::call_once(of, [&]() { // instance = std::shared_ptr<Logger>(new Logger()); // }); // return instance; // } log4cplus::Logger getLogger(){ return _logger; } ~Logger(){ log4cplus::Logger::shutdown(); } private: Logger(){ #pragma region 文件载入 //if (!exists("./Log/")) //{ // create_directory("./Log/"); //} //log4cplus::PropertyConfigurator::doConfigure(LOG4CPLUS_TEXT("log4cplus.cfg")); //_logger = log4cplus::Logger::getRoot(); #pragma endregion #pragma region 代码载入 log4cplus::initialize(); log4cplus::helpers::Properties consoleProperties; consoleProperties.setProperty(LOG4CPLUS_TEXT("Encoding"), LOG4CPLUS_TEXT("UTF-8")); log4cplus::SharedAppenderPtr CA(new log4cplus::ConsoleAppender(consoleProperties)); CA->setName(LOG4CPLUS_TEXT("CA")); log4cplus::tstring pattern = LOG4CPLUS_TEXT("[%D{%Y-%m-%d %H:%M:%S.%Q}] %-5p %m%n"); CA->setLayout(std::unique_ptr<log4cplus::Layout>(new log4cplus::PatternLayout(pattern))); log4cplus::helpers::Properties timeBasedProperties; timeBasedProperties.setProperty(LOG4CPLUS_TEXT("FilenamePattern"), LOG4CPLUS_TEXT("Log/%d{yyyy-MM-dd}.log")); timeBasedProperties.setProperty(LOG4CPLUS_TEXT("Schedule"), LOG4CPLUS_TEXT("DAILY")); timeBasedProperties.setProperty(LOG4CPLUS_TEXT("Append"), LOG4CPLUS_TEXT("true")); timeBasedProperties.setProperty(LOG4CPLUS_TEXT("MaxHistory"), LOG4CPLUS_TEXT("365")); timeBasedProperties.setProperty(LOG4CPLUS_TEXT("RollOnClose"), LOG4CPLUS_TEXT("false")); timeBasedProperties.setProperty(LOG4CPLUS_TEXT("CreateDirs"), LOG4CPLUS_TEXT("true")); timeBasedProperties.setProperty(LOG4CPLUS_TEXT("MaxFileSize"), LOG4CPLUS_TEXT("10MB")); timeBasedProperties.setProperty(LOG4CPLUS_TEXT("MaxBackupIndex"), LOG4CPLUS_TEXT("10")); timeBasedProperties.setProperty(LOG4CPLUS_TEXT("Encoding"), LOG4CPLUS_TEXT("UTF-8")); log4cplus::SharedAppenderPtr MR(new log4cplus::TimeBasedRollingFileAppender(timeBasedProperties)); pattern = LOG4CPLUS_TEXT("[%D{%Y-%m-%d %H:%M:%S.%Q}] %-5p %m%n"); MR->setLayout(std::unique_ptr<log4cplus::Layout>(new log4cplus::PatternLayout(pattern))); #pragma endregion _logger = log4cplus::Logger::getRoot(); _logger.setLogLevel(log4cplus::ALL_LOG_LEVEL); _logger.addAppender(CA); _logger.addAppender(MR); } private: log4cplus::Logger _logger; private: static boost::shared_ptr<Logger> instance; // static std::shared_ptr<Logger> instance; static std::once_flag of; }; #define LOG_TRACE(log) LOG4CPLUS_TRACE(Logger::getInstance()->getLogger(), log) #define LOG_DEBUG(log) LOG4CPLUS_DEBUG(Logger::getInstance()->getLogger(), log) #define LOG_INFO(log) LOG4CPLUS_INFO(Logger::getInstance()->getLogger(), log) #define LOG_WARN(log) LOG4CPLUS_WARN(Logger::getInstance()->getLogger(), log) #define LOG_ERROR(log) LOG4CPLUS_ERROR(Logger::getInstance()->getLogger(), log) #define LOG_FATAL(log) LOG4CPLUS_FATAL(Logger::getInstance()->getLogger(), log) #define TRACE(log) LOG_TRACE(log) #define DEBUG(log) LOG_DEBUG(log) #define INFO(log) LOG_INFO(log) #define ERROR(log) LOG_ERROR(log) #define FATAL(log) LOG_FATAL(log) #endif // LOGGER_H -
Logger.cpp
#include "Logger.h" boost::shared_ptr<Logger> Logger::instance = nullptr; //std::shared_ptr<Logger> Logger::instance = nullptr; std::once_flag Logger::of;
-
-
接下来,在入口函数中使用验证的Vcpkg所管理的包,编译运行
-
main.cpp
#include <QApplication> #include <QDebug> #include <QtNetwork/QTcpServer> #include <QWidget> #include <fmt/core.h> #include <iostream> #include <filesystem> #include <boost/any.hpp> #include "Logger.h" int main(int argc, char *argv[]) { QApplication a(argc, argv); fmt::print("hello {} with {}\n", "vcpkg", "cmake"); if (std::filesystem::exists("Info.log")){ qDebug() << "not found Info.log"; } boost::any arr = 1; qDebug() << boost::any_cast<int>(arr); LOG_INFO("上帝说,要有光,于是,就有了光."); QWidget w; w.show(); QTcpServer tcpServer(&w); return a.exec(); } -
编译运行非常顺利,执行结果如所料一般,查看日志Log/*.log:
[2022-08-25 16:09:10.945.181] INFO 上帝说,要有光,于是,就有了光.
-
在Visual Studio 2022中编译运行
其实这部分也没有什么好说明的,从2017开始Visual Studio大力推行使用CMake来进行项目构建
- 使用Visual Studio 2022打开项目上面的项目文件夹, 这时Visual Studio会自动创建CMakeCache,查看CMake输出
- 配置CMake Settings,Viusal Studio提供的GUI方式配置和Json方式的配置,这里只需要将QT_Dir、Qt5_Dir配置为
D:/Qt/5.12.12/msvc2017_64/lib/cmake/Qt5
,这里需要注意,我在QtCreator中使用的是x86-Debug的环境,我在Visual Studio中使用的是x64-Debug的环境
结语
使用Vcpkg来进行c++项目的包管理十分方便,相同语言、不同语言的子项目管理、引入等都不在话下,另外CMake、Vcpkg跨平台特性对于技术猿来说也是一件一学永逸的事情
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· AI Agent开发,如何调用三方的API Function,是通过提示词来发起调用的吗