基于CMake导入第三方库,以OpenCV为例

基于CMake导入第三方库,以OpenCV为例

目录

  • 基于CMake导入第三方库,以OpenCV为例
    • 前言
    • 直接导入
    • find package
    • 基于nuget进行包管理
    • 运行的问题

前言

除了自己写一个静态库或动态库,平时在开发过程,使用第三方库是常见的选择,这样可以避免重复“造轮子”,大大加快开发进度。CMake为使用第三方库提供多种管理方式,这里介绍3种,分别为直接导入,find package导入和基于nuget进行包管理。这章将以最常见的OpenCV库为例来说明3种管理方式,示例可在https://github.com/LeiChenIntel/wheels/tree/main/cmake_guide/sample5获取。

直接导入

1,设置环境变量“OPENCV_DIR”。
基于CMake导入第三方库,以OpenCV为例_第1张图片

2,在CMake中通过$ENV{OPENCV_DIR}获取环境变量,进而设置头文件包含路径和链接库路径,并链接对应的库。这里需要检查包含路径/build/include/build/x64/vc15/lib,如果和实际不符,CMake无法工作。

message("Link OpenCV build library manually")
add_definitions(-D LINK_OPENCV_LIB_MANUAL)
set(OPENCV_INC_DIR $ENV{OPENCV_DIR}/build/include)
set(OPENCV_LIB_DIR $ENV{OPENCV_DIR}/build/x64/vc15/lib)
target_include_directories(sample5 PUBLIC ${OPENCV_INC_DIR})
target_link_directories(sample5 PUBLIC ${OPENCV_LIB_DIR})
# project can change lib automatically with debug and release mode
target_link_libraries(sample5 debug opencv_world452d)
target_link_libraries(sample5 optimized opencv_world452)

3,如果要测试直接导入方式,在CMake构建工程时需使用:

cmake -DADD_OPENCV_LIB_MANUAL=ON -DADD_OPENCV_LIB_AUTO=OFF -DADD_OPENCV_LIB_NUGET=OFF ..

find package

如果只链接一个库,直接导入的方式相对简单,如果要多个库文件,一个一个写会显得繁琐。另一个问题,如果像直接导入中将头文件和库包含路径写死,一旦库结构发生调整,CMake将无法正确工作。因此,OpenCV提供了OpenCVConfig.cmake的方式来导入库,可以将所有库全部导入工程。
1,设置环境变量“OpenCV_DIR”(必须用这个变量名),确保路径下有OpenCVConfig.cmake文件。
基于CMake导入第三方库,以OpenCV为例_第2张图片
2,在CMake中用 find_package 导入库。在OpenCVConfig.cmake中有很多关于库的说明,比如新定义了很多宏,可以在CMake中直接使用。

message("Link OpenCV build library via OpenCVConfig.cmake")
add_definitions(-D LINK_OPENCV_LIB_AUTO)
find_package(OpenCV REQUIRED)
include_directories(sample5 ${OpenCV_INCLUDE_DIRS})
target_link_libraries(sample5 ${OpenCV_LIBS})

基于CMake导入第三方库,以OpenCV为例_第3张图片
3,如果要测试 find_package 导入方式,在CMake构建工程时需使用:

cmake -DADD_OPENCV_LIB_MANUAL=OFF -DADD_OPENCV_LIB_AUTO=ON -DADD_OPENCV_LIB_NUGET=OFF ..

基于nuget进行包管理

nuget是基于Visual Studio的包管理工具,降低第三方库的管理成本。在VS中可以在Tools->NuGet Package Manager中启动管理界面,在界面中可以搜索需要的库(boost_filesystem-vc140),指定加载的项目(sample5),选择库版本(Latest stable 1.76.0)。

基于CMake导入第三方库,以OpenCV为例_第4张图片
上面是基于VS界面的设置方式,如果在CMake构建工程时就将这些设置好无疑会让事情更简单。

1,要在packages.config.in中记录库信息,这些信息要与nuget服务器 https://www.nuget.org 对应,在搜索栏找到需要的库,找到库名:“opencv.win.native”和库版本:“320.1.1-vs141”,记录在packages.config.in中。
基于CMake导入第三方库,以OpenCV为例_第5张图片

  <package id="opencv.win.native" version="320.1.1-vs141" targetFramework="win" />

package config的更多信息可以看官方文档:https://docs.microsoft.com/zh-cn/nuget/reference/packages-config

2, 在CMake中包含库头文件,链接库文件。在VS里build时(在用CMake构建工程时不会下载库,下载是在build过程中发生的),第三方库会下载到./pakcages文件夹里,之后的目录结构取决于库本身,所以要检查目录结构并将其正确填写进CMake。

message("Link OpenCV via Nuget")
# Need file packages.config.in with packages information.
configure_file(packages.config.in ${CMAKE_CURRENT_BINARY_DIR}/packages.config NEWLINE_STYLE CRLF)
# After set OPENCV_PKG, sample5 should have been linked by "target_link_libraries(sample5 ${OPENCV_PKG})". However,
# the .targets file is only prepared for v141 (VS2017). OpenCV have to be linked manually when v142 (VS2019) used.
# set(OPENCV_PKG ${CMAKE_BINARY_DIR}/packages/opencv.win.native.320.1.1-vs141/build/native/opencv.win.native.targets)
target_include_directories(sample5 PUBLIC ${CMAKE_BINARY_DIR}/packages/opencv.win.native.320.1.1-vs141/build/native/include)
# target_link_libraries(sample5 ${OPENCV_PKG})
set(OPENCV_LIB_DIR
	${CMAKE_BINARY_DIR}/packages/opencv.win.native.320.1.1-vs141/build/native/lib/x64/v141/Debug
	${CMAKE_BINARY_DIR}/packages/opencv.win.native.320.1.1-vs141/build/native/lib/x64/v141/Release)
target_link_directories(sample5 PUBLIC ${OPENCV_LIB_DIR})
# target cannot judge debug/release lib automatically here.
if(OPENCV_LIB_NUGET_DEBUG)
	target_link_libraries(sample5
		opencv_videoio320d
		opencv_imgproc320d
		opencv_imgcodecs320d
		opencv_highgui320d
		opencv_core320d)
else()
	target_link_libraries(sample5
		opencv_videoio320
		opencv_imgproc320
		opencv_imgcodecs320
		opencv_highgui320
		opencv_core320)
endif()

3,如果要测试 nuget 库管理方式,在CMake构建工程时需使用:

cmake -DADD_OPENCV_LIB_MANUAL=OFF -DADD_OPENCV_LIB_AUTO=OFF -DADD_OPENCV_LIB_NUGET=ON ..

使用nuget的优势:
可以对第三方库进行版本管理,确保在不同机器上build都使用完全相同的第三方库,便于协同开发。在企业开发中,这是一个比较好的选项。
使用nuget的劣势:
因为每次build都要下载一份第三方库,开发机是需要接入网络的,build的工程会比较大。nuget的服务器上必须有需要的库,而且版本要符合需求,比如,理论上VS2019要vc142的库,VS2017要vc141,VS2015要vc140,不符合需求在加载过程中会遇到一些障碍。目前 nuget 应该只支持Visual Studio系列开发环境,如果用非MS开发环境如CLion库无法正常加载。

运行的问题

sample5作为一个简单的示例,具有读取图片并输出的功能,在找到正确的动态库(opencv_*320.dll)后应该能运行,

sample5.exe D:\opencv-logo.png

可能会出现无法找到zlib1.dll的问题,需要在网络上下载或在系统中找到并包含这个动态库。

你可能感兴趣的:(C++,cmake,c++,opencv,visual,studio,windows)