上两篇我们分别讲了如何配置opencv环境,以及如何编译opencv源码方便我们阅读。但我们还是无法调试我们的代码,无法以我们的程序作为入口来一步一步单点调试看opencv是如何执行的。
为此我们介绍两种调试opencv的方法。
1、通过VS配置来调试
在上一篇文章中,我们生成了opencv源码工程,基于该工程,我们可以生成debug版本的动态链接库opencv_world460d.dll,以及调试信息文件opencv_world460d.pdb。
我们想要调试opencv的源码,只需要将这两个文件拷贝到我们自己项目的可执行文件的同级目录内即可。
例如我们一直在使用的test_link_opencv这个工程:
完成拷贝后,直接在工程中打断点进行单步调试,即可进入opencv源码内调试了。
2、通过在opencv源码内部进行调试
上面的方法可以使我们基于我们自己的项目,来调试opencv的源码。但上篇文章中我们已经构建了opencv源码工程了,如果仅仅是为了学习、阅读源码,我们可以在opencv源码工程内进行调试。
首先opencv提供了许多examples示例程序,我们在cmake-gui的options中,找到选项
-
BUILD_EXAMPLES:构建示例程序
并勾选,然后重新点击configure和Generate:
然后重新打开我们的VS工程,就可以找到官方提供的例程了:
我们可以将配置改为Debug x64模式,再将其中一个例程设为可执行程序,就可以直接调试了。
如果例程的内容不是你想调试的内容,那你也可以建一个自己的例程项目,然后在该项目里写自己想要调试的代码,这要怎么做到呢?
我们在opencv\sources\samples\cpp\CMakeLists.txt文件中,可以看到该cmake文件对该samples路径下的每一个.cpp文件,都应用了
ocv_define_sample(tgt ${sample_filename} ${package})
这个函数,这个函数位于opencv\sources\samples\samples_utils.cmake:
# Utility function: adds sample executable target with name "example_<group>_<file_name>"
# Usage:
# ocv_define_sample(<output target> <relative filename> <group>)
function(ocv_define_sample out_target source sub)
get_filename_component(name "${source}" NAME_WE)
set(the_target "example_${sub}_${name}")
add_executable(${the_target} "${source}")
add_dependencies(${parent_target} ${the_target})
set(${out_target} ${the_target} PARENT_SCOPE)
endfunction()
该函数将每一个samples路径下的.cpp文件,都单独生成为了一个exe可执行项目,因此呢,我们要往samples内添加我们自己的项目也很简单,只需要在路径
opencv\sources\samples\cpp\文件夹内添加一个.cpp文件即可。
我们添加一个sherad_opencv.cpp文件:
然后重新在cmake-gui内点击configure和Generate按钮,然后重新打开opencv的VS源码工程,就可以看到我们添加的shredOpencv项目了:
前面几篇文章我们都是围绕Visual Studio 2019这个IDE来展开的,IDE为我们做了太多太多的事情,虽然使用很方便,但工程管理太臃肿,你的项目都会夹带着诸如.sln、.vcxproj、.filters、.user等等各种VS自己的工程文件:
甚至vs会给你自动生成很多诸如DLLMain、pch.h、pch.cpp等等这些完全可以省略的优化文件。
而使用cmake却很简捷,你只需要编写好你的cmake工程文件,就可以简捷的管理你的工程,就像opencv使用cmake来管理一样,不仅简捷,还可以跨平台。
简捷体现在哪呢,使用cmake来管理你的项目,所有的配置选项都会在cmake-gui的options界面显示出来供使用者配置,且源码和工程是分离的(也就是source和build是分离的)。
所以本教程同样采取cmake来管理我们的项目,项目结构如下:
项目采用cmake来管理:
-
CMakeModules:一些cmake文件
-
image:存放本教程用到的图片
-
MCV_Code和Samples_Code:教程代码
-
Tutorial:教程,主要是文档
-
README.md
学习本教程,学会cmake是你必然的收获。因为学习cmake没有什么方式比参与一个由cmake管理的项目来的更快更好了。
1)cmake学习资源
学习cmake首推cmake的官方教程:
https://cmake.org/cmake/help/latest/guide/tutorial/
然后推荐一本开源书籍《cmake菜谱》:
https://www.bookstack.cn/read/CMake-Cookbook/README.md
2)如何使用cmake管理项目
我们来简单的介绍一下如何使用cmake来管理项目,我们以我们前几篇文章一直在使用的test_link_opencv这个项目来说,这个项目是直接使用VS创建的一个控制台应用程序,也就是生成exe可执行文件,我们现在先回退到链接opencv库以前的状态。
如何使用cmake来管理、生成这样一个exe项目呢:
直接创建如上三个空文件。
CMakeLists.txt名称必须如此,这是cmake的设定,我们通过在该文件内写cmake代码来完成项目的配置和管理。另外再创建一个test.cpp和test.h,我们会将这两个文件编译成一个test.exe可执行文件。
在CMakeLists.txt中写如下cmake代码:
#工程基础配置
cmake_minimum_required(VERSION 3.21 FATAL_ERROR)# 设置最低cmake版本
project(TestCMake LANGUAGES CXX)# 创建一个工程,对应VS里的解决方案,并设置工程的语言为C++
set(CMAKE_CXX_STANDARD 17)# 设置C++标准为C++17,CMAKE_CXX_STANDARD变量为cmake的内置属性变量
# 添加文件
file(GLOB _SRCS test.cpp test.h) #将.cpp .h文件,都添加到_SRCS变量中
add_executable(${PROJECT_NAME} ${_SRCS})# 将.cpp .h编译为一个exe
对以上代码做几点解释,如果还不懂的,哪个cmake语句不懂,就去百度哪个,然后再去看官方文档教程。
-
cmake_minimum_required和project()是每个cmake工程都必须要有的。
-
cmake有很多内置类型,我们不需要声明这些类型cmake就能知道它的含义,我们只需要直接使用set()语句对这些变量进行设置,cmake就会按照我们设置的方式运行,例如上面程序中的CMAKE_CXX_STANDARD,就代表我们编译我们工程时,使用哪个C++的标准,上面时使用了C++17标准。
-
file()函数可以将文件整合到一个变量中,上面代码中的变量为_SRCS,变量可以随意命名,它可以理解为一个列表,里面存储了test.cpp test.h,当我们项目的文件多的时候,可以一股脑的都添加到一个变量里
-
add_executable()是将文件编译为一个exe程序,上面我们用到了它的两个参数,分别是生成目标文件exe的目标名称,我们直接使用了我们的项目名称。第二个参数就是我们要编译的文件
-
cmake访问变量,都是通过${变量名}来访问的
完成上面代码后,我们仿照编译opencv库的方式,来编译我们自己的cmake项目:
打开cmake-gui,选择源码路径、build路径后,点击Configure、Generate按钮:
可以看到配置、生成均成功了,在中间的options选项区域,有两个红色的选项,红色我们前面也说过,代表这两个选项第一次出现在页面上,用来提示使用者的,并不代表出错。
我们在我们短短的几行代码中,并没有添加任何选项,所以页面上出来的这两个选项是cmake默认自动生成的:
-
CMAKE_CONFIGURATION_TYPES:项目可构建的类型,比我们熟知的Release、Debug还多了两个,大家自行百度
-
CMAKE_INSTALL_PREFIX:项目安装目录,本项目用不上,自行百度
点击cmake-gui页面上的Open Project按钮,可以直接打开我们编译生成的VS2019工程:
我们可以看到三个内容:
-
配置选项有四个,就是我们上面提到的Debug;Release;MinSizeRel;RelWithDebInfo
-
左侧文件书内有我们的TestCMake解决方案,以及我们的同名项目TestCMake,里面包含test.cpp和test.h
-
打开test.cpp,里面是空白的,因为我们没有往里面写任何东西
现在我们编写一个经典的hello代码:
#include <iostream>
#include "test.h"
using namespace std;
int main()
{
cout << "hello cmake!" << endl;
return 0;
}
将我们的TestCMake项目设为启动项。然后运行:
大功告成!
暂无评论内容