find_package可以用来查找第三方模块,find_package的两种模式,一种是Module模式,另一种叫做Config模式
(1)在Module模式中,cmake需要找到一个叫做Find
的文件。这个文件负责找到库所在的路径,为我们的项目引入头文件路径和库文件路径。cmake搜索这个文件的路径有两个,一个是上文提到的cmake安装目录(即CMAKE_ROOT变量)下的share/cmake-
目录,另一个是我们指定的CMAKE_MODULE_PATH的所在目录。使用时不需要加后缀.cmake
(2)如果Module模式搜索失败,没有找到对应的Find
文件,则转入Config模式进行搜索。它主要通过
or
这两个文件来引入我们需要的库。
# 定位到某个包
set(OpenCV_DIR "/usr/lib/opencv_300/build")
查找多个包的配置文件,可以将这些配置文件都统一放在一个命名为cmake的文件夹下,然后设置变量CMAKE_PREFIX_PATH变量指向这个cmake文件夹路径,需要注意根据上述的匹配规则,此时每个包的配置文件需要单独放置在命名为包名的文件夹下(文件夹名不区分大小写),否则会提示找不到。
如果找到了模块则CMake会定义这几个变量XXX_FOUND、XXX_INCLUDE_DIRS(头文件目录)、XXX_LIBRARIES(库文件)、XXX_LINK_DIRECTORIES(库所在目录)
如:OpenCV_FOUND
、OpenCV_INCLUDE_DIRS
等
# 一个简单示例
cmake_minimum_required(VERSION 3.4.1)
project(helloworld)
add_executable(helloworld hello.c)
find_package(BZip2)
if(BZIP2_FOUND)
include_directories(${BZIP_INCLUDE_DIRS})
target_link_libraries(helloworld ${BZIP2_LIBRARIES})
endif(BZIP2_FOUND)
对于原生支持Cmake编译和安装的库通常会安装Config模式的配置文件到对应目录,这个配置文件直接配置了头文件库文件的路径以及各种cmake变量供find_package使用。而对于非由cmake编译的项目,我们通常会编写一个Find
,通过脚本来获取头文件、库文件等信息。通常,原生支持cmake的项目库安装时会拷贝一份XXXConfig.cmake到系统目录中,因此在没有显式指定搜索路径时也可以顺利找到。
(3)如果没有.cmake
文件而且自己不想写.cmake
文件,那就不用find_package
,简单粗暴:
#find_package就是这么实现的
#头文件目录(是个目录的绝对路径)
find_path( NAMES XX.h PATHS /usr/include /usr\local/include/ ...)
#库文件(是个文件的绝对路径)
find_library( NAMES lib-name PATHS /usr/lib /usr/local/lib ...)
CMAKE_INCLUDE_PATH:find_path
默认会去这里找,当然指定写到PATHS后面更好
CMAKE_LIBRARY_PATH:find_library
默认会去这里找,当然指定写到PATHS后面更好
set(CMAKE_INCLUDE_PATH /usr/local/include/opencv
/usr/include)
find_path(CV_INCLUDE_DIRS NAMES cv.h PATHS CMAKE_INCLUDE_PATH)
# 在指定目录下寻找头文件和动态库文件的位置,可以指定多个目标路径
find_path(ADD_INCLUDE_DIR libadd.h /usr/include/ /usr/local/include ${CMAKE_SOURCE_DIR}/ModuleMode)
find_library(ADD_LIBRARY NAMES add PATHS /usr/lib/add /usr/local/lib/add ${CMAKE_SOURCE_DIR}/ModuleMode)
if (ADD_INCLUDE_DIR AND ADD_LIBRARY)
set(ADD_FOUND TRUE)
endif (ADD_INCLUDE_DIR AND ADD_LIBRARY)
version和EXACT: 都是可选的,version指定的是版本,如果指定就必须检查找到的包的版本是否和version兼容。如果指定EXACT则表示必须完全匹配的版本而不是兼容版本就可以。
QUIET可选字段,表示如果查找失败,不会在屏幕进行输出(但是如果指定了REQUIRED字段,则QUIET无效,仍然会输出查找失败提示语)。
MODULE 可选字段。前面提到说“如果Module模式查找失败则回退到Config模式进行查找”,但是假如设定了MODULE选项,那么就只在Module模式查找,如果Module模式下查找失败并不回落到Config模式查找。
REQUIRED可选字段。表示一定要找到包,找不到的话就立即停掉整个cmake。而如果不指定REQUIRED则cmake会继续执行。
COMPONENTS,components:可选字段,表示查找的包中必须要找到的组件(components),如果有任何一个找不到就算失败,类似于REQUIRED,导致cmake停止执行。
CMakeLists.txt
cmake_minimum_required(VERSION 3.14.4) # cmake最小版本限制
PROJECT(test)
message("${PROJECT_SOURCE_DIR}/opencv-3.4.1")
# 寻找OpenCV库
set(OpenCV_DIR "${PROJECT_SOURCE_DIR}/opencv/opencv/build")
find_package(OpenCV REQUIRED)
# 打印信息
message(STATUS " version:${OpenCV_VERSIOn}")
message(STATUS "libraries:${OpenCV_LIBS}")
message(STATUS "include path:${OpenCV_INCLUDE_DIRS}")
# 添加头文件
include_directories(${OpenCV_INCLUDE_DIRS})
# 将原代码添加到此项目的可执行文件
add_executable(test_opencv test_opencv.cpp)
# 链接OpenCV库
target_link_libraries(test_opencv ${OpenCV_LIBS} )
注:window环境需要下载官方exe文件进行安装opencv。使用cmake编译opencv源码因库文件不足会出错
test_opencv.cpp
#include
#include
using namespace std;
using namespace cv;
int main()
{
// 读入一张图片
Mat img = imread("D:\\Code\\demo\\demo.png");
// 创建一个名为 "图片"窗口
namedWindow("图片");
// 在窗口中显示图片
imshow("图片", img);
// 等待6000 ms后窗口自动关闭
waitKey(6000);
// system("pause");
return 0;
}