Clion2023版本集成了vcpkg包管理,很好用,但也很多坑,调试了一天半的时间,基本上搞通了,记录一下。
首先Clion创建新项目study,在左侧,找到vcpkg的按钮。
点击,然后会出现在界面的左下侧
第一次使用会提示下载。如果是想要全局使用,就安装到其他硬盘,如果每个项目单独配置,建议安装在项目的根目录(类似于anaconda/pip 虚拟环境全局环境)。我自己的配置如下图。
然后,可以愉快的通过vcpkg安装包了。但是!!!第一个坑就来了。齿轮这里的自动更改一定要取消掉。
原因在于:vcpkg有两种操作方式。一个类似于python中的requirements.txt安装(vcpkg.json),一个类似于pip手动安装。但是Clion过于灵活,容易这两个同时进行,就成大坑了。
因为vcpkg的第一种方法,是自己把包的版本号之类的配置信息写在vcpkg.json中,通过命令自动根据json文件下载,一旦通过这个方式,就不能再自己单独安装了(不能./vcpkg install XXX 以及Clion一键安装),否则会报错,会提示安装失败,或者就是包链接不成功。
建议用Clion集成的方法,搜索并点击安装键安装,这样方便。同时,出现了第二个坑,不要点击添加到vcpkg.json,理由同上,不要让项目中出现vcpkg.json。第三个坑,一定一定这个编译环境(三元组)选择要对应的上 设置中 工具链的架构!
我用的msvc,x64那就和x64-windows对应上,一定要对应上。比如安装zbar(mchehab-zbar)时,会默认安装x32位的,一定要注意。
其他的就是小坑了。比如工作目录要对应上:
CMake要加上(Clion会默认添加):例如“DCMAKE_TOOLCHAIN_FILE=C:\Users\62359\Desktop\study\vcpkg\scripts\buildsystems\vcpkg.cmake”
针对于我这个,把vcpkg安装到单独的项目下的情况,在CMakeLists.txt中,设置一下路径。
set(CMAKE_TOOLCHAIN_FILE "${CMAKE_CURRENT_SOURCE_DIR}/vcpkg/scripts/buildsystems/vcpkg.cmake"
CACHE STRING "Vcpkg toolchain file")
总体的CMakeLists.txt编写:
cmake_minimum_required(VERSION 3.25)
project(study)
set(CMAKE_TOOLCHAIN_FILE "${CMAKE_CURRENT_SOURCE_DIR}/vcpkg/scripts/buildsystems/vcpkg.cmake"
CACHE STRING "Vcpkg toolchain file")
set(CMAKE_CXX_STANDARD 20)
add_executable(study main.cpp)
set(OpenCV_DIR "${VCPKG_INSTALLED_DIR}/x64-windows/share/opencv4")
find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})
target_link_libraries(${PROJECT_NAME} PRIVATE ${OpenCV_LIBS})
set(ZBAR_INCLUDE_DIRS ${_VCPKG_INSTALLED_DIR}/x64-windows/include)
set(ZBAR_LIBRARIES ${_VCPKG_INSTALLED_DIR}/x64-windows/lib/zbar.lib)
include_directories(${ZBAR_INCLUDE_DIRS})
target_link_libraries(${PROJECT_NAME} PRIVATE ${ZBAR_LIBRARIES})
这里第四个大坑!有的库例如opencv,vcpkg做了适配,能直接find_package(OpenCV REQUIRED)。
但是,像zbar就没有适配,如果写了,会报错:
Could not find a package configuration file provided by "ZBAR" with any of the following names:ZBARConfig.cmake zbar-config.cmake
这是因为没适配,导致没有cmake配置文件。这样只能自己去写路径了。照着我的写就好了。
最后给一个demo:
#include <iostream>
#include <filesystem>
#include <opencv2/opencv.hpp>
#include <zbar.h>
namespace fs = std::filesystem;
int main(){
//std::cout << "Current working directory is " << fs::current_path() << std::endl;
cv::Mat image;
zbar::ImageScanner scanner;
// 启用所有的条码检测
scanner.set_config(zbar::ZBAR_NONE, zbar::ZBAR_CFG_ENABLE, 1);
try{
image = cv::imread("image/fact.jpg", cv::IMREAD_GRAYSCALE);
zbar::Image zbar_image(image.cols, image.rows, "Y800", image.data, image.cols * image.rows); // 创建zbar::Image对象
int num_symbols = scanner.scan(zbar_image);
std::cout<< "num_symbols = " <<num_symbols <<std::endl;
if (num_symbols > 0) {
for (zbar::Image::SymbolIterator symbol = zbar_image.symbol_begin(); symbol != zbar_image.symbol_end(); ++symbol) {
std::vector<cv::Point> location;
for (int i = 0; i < symbol->get_location_size(); ++i) {
location.emplace_back(symbol->get_location_x(i), symbol->get_location_y(i));
}
cv::polylines(image, location, true, cv::Scalar(0, 255, 0), 2);
}
}
}
catch (cv::Exception& e) {
std::cerr << "Error: " << e.msg << std::endl;
}
cv::imshow("Image", image);
cv::waitKey(0);
}
结果就出来了。命令行会有很多日志,这些是有些opencv内置的库没装上,没有任何问题。当然如果不想看到这些,可以更改opencv的日志等级,
[ INFO:0@0.138] global registry.impl.hpp:114 cv::highgui_backend::UIBackendRegistry::UIBackendRegistry UI: Enabled backends(4, sorted by priority): GTK(1000); GTK3(990); GTK2(980); WIN32(970) + BUILTIN(WIN32UI)
[ INFO:0@0.138] global plugin_loader.impl.hpp:67 cv::plugin::impl::DynamicLib::libraryLoad load C:\Users\62359\Desktop\study\cmake-build-debug\opencv_highgui_gtk470_64.dll => FAILED
[ INFO:0@0.140] global plugin_loader.impl.hpp:67 cv::plugin::impl::DynamicLib::libraryLoad load opencv_highgui_gtk470_64.dll => FAILED
[ INFO:0@0.140] global plugin_loader.impl.hpp:67 cv::plugin::impl::DynamicLib::libraryLoad load C:\Users\62359\Desktop\study\cmake-build-debug\opencv_highgui_gtk3470_64.dll => FAILED
[ INFO:0@0.141] global plugin_loader.impl.hpp:67 cv::plugin::impl::DynamicLib::libraryLoad load opencv_highgui_gtk3470_64.dll => FAILED
[ INFO:0@0.142] global plugin_loader.impl.hpp:67 cv::plugin::impl::DynamicLib::libraryLoad load C:\Users\62359\Desktop\study\cmake-build-debug\opencv_highgui_gtk2470_64.dll => FAILED
[ INFO:0@0.143] global plugin_loader.impl.hpp:67 cv::plugin::impl::DynamicLib::libraryLoad load opencv_highgui_gtk2470_64.dll => FAILED
[ INFO:0@0.143] global backend.cpp:90 cv::highgui_backend::createUIBackend UI: using backend: WIN32 (priority=970)
[ INFO:0@0.144] global window_w32.cpp:3008 cv::impl::Win32BackendUI::createWindow OpenCV/UI: Creating Win32UI window: Image (1)
[ INFO:0@0.193] global registry_parallel.impl.hpp:96 cv::parallel::ParallelBackendRegistry::ParallelBackendRegistry core(parallel): Enabled backends(3, sorted by priority): ONETBB(1000); TBB(990); OPENMP(980)
[ INFO:0@0.194] global plugin_loader.impl.hpp:67 cv::plugin::impl::DynamicLib::libraryLoad load C:\Users\62359\Desktop\study\cmake-build-debug\opencv_core_parallel_onetbb470_64d.dll => FAILED
[ INFO:0@0.195] global plugin_loader.impl.hpp:67 cv::plugin::impl::DynamicLib::libraryLoad load opencv_core_parallel_onetbb470_64d.dll => FAILED
[ INFO:0@0.196] global plugin_loader.impl.hpp:67 cv::plugin::impl::DynamicLib::libraryLoad load C:\Users\62359\Desktop\study\cmake-build-debug\opencv_core_parallel_tbb470_64d.dll => FAILED
[ INFO:0@0.197] global plugin_loader.impl.hpp:67 cv::plugin::impl::DynamicLib::libraryLoad load opencv_core_parallel_tbb470_64d.dll => FAILED
[ INFO:0@0.197] global plugin_loader.impl.hpp:67 cv::plugin::impl::DynamicLib::libraryLoad load C:\Users\62359\Desktop\study\cmake-build-debug\opencv_core_parallel_openmp470_64d.dll => FAILED
[ INFO:0@0.199] global plugin_loader.impl.hpp:67 cv::plugin::impl::DynamicLib::libraryLoad load opencv_core_parallel_openmp470_64d.dll => FAILED
opencv日志等级(用chatgpt偷懒一下):
cv::LOG_LEVEL_SILENT:不输出任何日志信息
cv::LOG_LEVEL_FATAL:只输出致命错误信息
cv::LOG_LEVEL_ERROR:输出错误信息和致命错误信息
cv::LOG_LEVEL_WARNING:输出警告、错误和致命错误信息
cv::LOG_LEVEL_INFO:输出一般信息、警告、错误和致命错误信息
cv::LOG_LEVEL_DEBUG:输出所有信息,包括调试信息
默认情况下,OpenCV的日志级别为cv::LOG_LEVEL_INFO,
会输出一般信息、警告、错误和致命错误信息。
如果您想屏蔽警告信息,可以将日志级别设置为cv::LOG_LEVEL_ERROR或cv::LOG_LEVEL_FATAL。
具体来说,您可以在程序的入口处添加以下代码:
cv::utils::logging::setLogLevel(cv::utils::logging::LOG_LEVEL_ERROR);
这样就可以将日志级别设置为cv::LOG_LEVEL_ERROR,只输出错误和致命错误信息,而不会输出警告信息。
至此,大功告成。