目录

Ubuntu20使用CMake源码编译安装OpenCV

安装OpenCV4,记录一下问题和经验

过程

克隆源码

编译安装

1
2
3
4
5
mkdir build
cd build
cmake ..
make -j8
sudo make install

问题解决

  • 找不到openjpeg.h

    • 【原因】CMake默认的搜索路径是/usr/include,但是这个头文件实际上在子目录/usr/include/openjpeg里,而CMake不会递归搜索
    • 【解决】我把整个文件夹里的4个头文件从子目录移到了/usr/include里;第二种解决方法是配置OpenCV的CMake的搜索路径
  • undefined reference to TIFFIsTiled@LIBTIFF_4.0

    • 链接问题,上网搜索后得知需要在CMake的时候打开DBUILD_TIFF=ON选项,就会编译这个库
  • Conda导致库混淆

    • 事实证明,在zshrc里预先初始化Conda会导致很多问题……这个是会导致库混乱。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    CMake Warning at src/CMakeLists.txt:255 (add_executable):
      Cannot generate a safe runtime search path for target bedrough_test because
      files in some directories may conflict with libraries in implicit
      directories:
    
        runtime library [LIBRARY] in /usr/lib/[PATH] may be hidden by files in:
          /home/[USER]/anaconda3/lib
    
      Some of these libraries may not be found correctly.
    
    1
    
     - 【解决】想办法让CMake在编译的时候看不到conda。`conda deactivate`不行,似乎不能改掉一些环境变量的设置,所以先在zshrc里注释掉conda的初始化代码,再开一个终端,在新终端里编译
    

疑惑

  • 有个问题,虽然安装的是opencv4,但文件目录是opencv4/opencv2/xxx.h,怪哉

OpenCV HelloWorld

安装完后,就是跑一个小例子试验一下咯

代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>

using namespace cv;

int main(int argc, char** argv) {

	//create a gui window:
	namedWindow("Output",1);

	//initialize a 120X350 matrix of black pixels:
	Mat output = Mat::zeros( 120, 350, CV_8UC3 );

	//write text on the matrix:
	putText(output,
			"Hello World :)",
			Point(15,70),
			FONT_HERSHEY_PLAIN,
			3,
			Scalar(0,255,0),
			4);

	//display the image:
	imshow("Output", output);

	//wait for the user to press any key:
	waitKey(0);

	return 0;

}

CMake配置

  • 添加这三行,其中YourProject改为自己工程的名字
1
2
3
find_package(OpenCV REQUIRED)
target_include_directories(YourProject ${OpenCV_INCLUDE_DIRS})
target_link_libraries(YourProject ${OpenCV_LIBS})

后记:CMake拾遗

系统指令**不区分大小写,变量和字符串区分**大小写 CMake本身不做构建,它的generator做构建,这个generator可以是make/ninja等

CMake命令行

cmake -S -B build-B是指定构建目录,-S是指定代码目录

CMake默认变量

  • TODO

Find_Package的工作机理

它是去指定路径搜索某个cmake脚本,然后这个脚本再去具体找某个库,有两种搜索模式。找完后,通过设置一些变量来给调用它的父脚本使用,比如是否找到,头文件和二进制文件路径等。

  1. Module Mode
    • 搜索路径:CMAKE_MODULE_PATH,一般为空,而找的是Find<PackageName>.cmake 这个脚本。值得注意的是,此脚本一般并不是库自己提供的,而是操作系统、CMake自己等,因此常常会找到旧版的库。
    • 《Modern CMake》里提到这种一般是适用于非原生支持CMake的项目的,(如果你是库的开发者)不推荐用这种
  2. Config Mode
    • <lowercasePackageName>-config.cmake or <PackageName>Config.cmake脚本,如果指定了版本,还会找<lowercasePackageName>-config-version.cmake or <PackageName>ConfigVersion.cmake这俩。
    • 搜索路径是一系列路径的集合,在不同操作系统略有不同
    • 通常,原生支持cmake的项目库安装时会拷贝一份XXXConfig.cmake到系统目录中

将会设置的变量

  • <PackageName>_FOUND 表示是否找到
  • <LibaryName>_INCLUDE_DIR或者<LibaryName>_INCLUDES,库的头文件所在
  • <LibaryName>_LIBRARY或者 <LibaryName>_LIBRARIES,库的二进制文件所在

函数签名

1
2
3
4
find_package(<PackageName> [version] [EXACT] [QUIET] [MODULE]
             [REQUIRED] [[COMPONENTS] [components...]]
             [OPTIONAL_COMPONENTS components...]
             [NO_POLICY_SCOPE])
  • REQUIRED表示这个库是必要的,如果找不到就会fatal error终止编译
  • MODULE表示仅使用Module方法。默认地,CMake会先用Module Mode,如果找不到再用Config Mode

target_include_directories

  • 关于target_include_directoriesinclude_directories的区别,见StackOverFlow

  • 概括来说就是,前者只是为指定目标添加包含目录,有着tareget scope,而后者对整个文件都有影响,有着全局作用域,所以推荐用前者

  • 还有一个是与Public/Private连用的时候作用域扩展的区别,先不看了,如果用到了再看

  • 关于关键字public/interface/private,参考这里 ,讲的清楚。概括来说就是如果你这个库只给自己用,在对外的头文件不包含,外界不知道这个库的存在,就private;如果只给外界用,内部不用库(可能只用了头文件里的东西),那么就interface。如果都有那么就public。原文转述一下:

实际上,这三个关键字指定的是目标文件依赖项的使用范围(scope)或者一种传递(propagate)官方说明

可执行文件依赖 libhello-world.so, libhello-world.so 依赖 libhello.so 和 libworld.so。

  1. main.c 不使用 libhello.so 的任何功能,因此 libhello-world.so 不需要将其依赖—— libhello.so 传递给 main.c,hello-world/CMakeLists.txt 中使用 PRIVATE 关键字;
  2. main.c 使用 libhello.so 的功能,但是libhello-world.so 不使用,hello-world/CMakeLists.txt 中使用 INTERFACE 关键字;
  3. main.c 和 libhello-world.so 都使用 libhello.so 的功能,hello-world/CMakeLists.txt 中使用 PUBLIC 关键字;

参考资料