CMake指令入门 ——以构建OpenCV项目为例

CMake指令入门 ——以构建OpenCV项目为例

转自:https://blog.csdn.net/sandalphon4869/article/details/100589747

一、安装

sudo apt-get install cmake

安装好后,输入

cmake -version

如果出现了cmake的版本显示,那么说明安装成功

二、cmake编译

cmake的作用就是将在IDE编译器中的编译功能拿出来,可以在终端上完成。类似于vim和文本编辑器。

cmake的编译方式:

  • 内部构建(in-source-build)

  • 外部构建(out-of-source-build)

两者的区别仅仅是前者将生成的编译文件和源代码、CMakeLists.txt 混杂在一起,后者就只是创建了一个文件夹 build 存储生成的编译文件,更好删除编译生成的文件而已(直接删文件夹)。

三、语法

1. 基本语法

  • 指令是大小写无关的,参数和变量是大小写相关的。但推荐你全部使用大写指令。

  • 变量使用 ${}方式取值,但是在 IF 控制语句中是直接使用变量名。如:${SRC_LIST}

  • 指令(参数 1 参数 2…) 参数使用括弧括起,参数之间使用空格或分号分开。

    如:ADD_EXECUTABLE(hello main.c func.c) 或者 ADD_EXECUTABLE(hello main.c;func.c)

  • 注释:# comment

2. 指令

搞清当前目录的意思:

  • CMakeLists.txt 中的 . 表示当前目录是CMakeLists.txt文件所在的目录,而非执行时终端的当前目录。

  • cmake . 这条终端命令是执行时终端的当前目录。

(1) PROJECT()

PROJECT(projectname [CXX] [C] [Java])

总结:定义工程名称,并可指定工程支持的语言。

  • 定义工程名称:如 PROJECT(HELLO) ,那么工程的名称就是 HELLO

  • 支持的语言列表:支持的语言列表是可以忽略的, 默认情况表示支持所有语言。
    如指定C++:PROJECT(HELLO CXX)

  • 这个指令隐式的定义了四个 cmake 变量:

    • <projectname>_BINARY_DIR 以及 <projectname>_SOURCE_DIR(格式,并非实际的变量)。对于这个工程就是 HELLO_BINARY_DIRHELLO_SOURCE_DIR (之后就可以直接使用了这两个变量),使用 <projectname>_BINARY_DIR 这个是无效的。
      PROJECT_BINARY_DIRPROJECT_SOURCE_DIR 变量。
    • 他们的值分别跟 HELLO_BINARY_DIRHELLO_SOURCE_DIR 一致。区别是这两个会自动根据工程名字的变化而变化。
    • 建议以后直接使用 PROJECT_BINARY_DIRPROJECT_SOURCE_DIR,即使修改了工程名称,也不会影响这两个变量。如:从HELLO该为WORLD,那么前者就得写成WORLD_BINARY_DIRWORLD_SOURCE_DIR,但后者还是 PROJECT_BINARY_DIRPROJECT_SOURCE_DIR

(2) CMAKE_MINIMUM_REQUIRED()

CMAKE_MINIMUM_REQUIRED(VERSION 3.10)

cmake最低版本

(3) SET()

SET(VAR [VALUE] [CACHE TYPE DOCSTRING [FORCE]])

作用:定义变量的值

比如:

  • 如果有多个源文件,也可以定义成:SET(SRC_LIST main.c t1.c t2.c)

  • 可以用 "" 来处理包含空格的文件名:SET(SRC_LIST "hello world.cpp")(建议使用方式)

  • 使用c++11特性:set(CMAKE_CXX_FLAGS "${CAMKE_CXX_FLAGS} -std=c++11"),防止出现因为c++11才有的编译错误,比如 error: ‘to_string’ is not a member of ‘std’

  • 设置编译模式 Build Type,要加引号,不加可能报错。

    • Debug模式:set(CMAKE_BUILD_TYPE "Debug")
    • Release模式:set(CMAKE_BUILD_TYPE "Release"),更快。

(4) MESSAGE()

MESSAGE([SEND_ERROR | STATUS | FATAL_ERROR] "message to display")

作用:在cmake编译过程中向终端输出用户定义的信息。

三种信息类型:

  • SEND_ERROR:产生错误,生成过程被跳过

  • STATUS:输出前缀为 -- 的信息。

  • FATAL_ERROR:立即终止所有 cmake 过程

输出内容:"hello ${<variant name>}"

比如:

PROJECT(HELLO)
SET(SRC_LIST main.cpp)
MESSAGE(STATUS "The value of HELLO_SOURCE_DIR is${HELLO_SOURCE_DIR}" )
ADD_EXECUTABLE(hello ${SRC_LIST})

输出:

...
The value of HELLO_SOURCE_DIR is/home/song/code
...

ps:引号的作用是保留空格

  • "hello world ${HELLO_SOURCE_DIR}":输出为 hello world /home

  • hello world ${HELLO_SOURCE_DIR}:输出为 helloworld/home

(5) AUX_SOURCE_DIRECTORY()

①基本含义

AUX_SOURCE_DIRECTORY(dir VARIABLE)

作用是发现一个目录 dir 下所有的源代码文件并将列表存储在一个变量中,这个指令临时被用来自动构建源文件列表。因为目前 cmake 还不能自动发现新添加的源文件。 (本目录为CMakeLists.txt所在的目录)

比如:

AUX_SOURCE_DIRECTORY(. SRC_LIST)
ADD_EXECUTABLE(main ${SRC_LIST})

将本目录下的源代码文件添加到SRC_LIST变量中,再将这些文件编译成生成文件。

②子目录

注意:如果本目录下有子目录,是不会将子目录下的源代码文件添加进去的,得手动打出来。比如:

# 本目录下的子目录subDir
AUX_SOURCE_DIRECTORY(./subDir SRC_LIST)

③可添加多个

这两个一起添加进入 SRL_LIST,并不是后者覆盖前者。

AUX_SOURCE_DIRECTORY(./src/text SRC_LIST)
AUX_SOURCE_DIRECTORY(./src/serial SRC_LIST)

(6) ADD_SUBDIRECTORY

ADD_SUBDIRECTORY(source_dir [binary_dir] [EXCLUDE_FROM_ALL])

这个指令用于向当前工程添加存放源文件的子目录,并可以指定中间二进制和目标二进制存放的位置。

EXCLUDE_FROM_ALL参数的含义:将这个目录从编译过程中排除,比如,工程 的 example,可能就需要工程构建完成后,再进入 example 目录单独进行构建(当然,你 也可以通过定义依赖来解决此类问题)。

比如:

将 src 子目录加入工程,并指定编译输出(包含编译中间结果)路径为bin 目录。

(7) FIND_PACKAGE()

FIND_PACKAGE(<name> [major.minor] [QUIET] [NO_MODULE] 
[[REQUIRED|COMPONENTS] [componets...]])

参数:

REQUIRED 参数:如果使用了这个参数,说明这 个链接库是必备库,如果找不到这个链接库,则工程不能编译。

功能:只找一个名为 name 的包(后面都是修饰条件),所以如果要找多个包,要分多个FIND_PACKAGE() 写。

比如:

  • OpenCV3:

    find_package(OpenCV REQUIRED)
    
  • ROS:

    find_package(catkin REQUIRED COMPONENTS roscpp rospy std_msgs)
    

(8) INCLUDE_DIRECTORIES()

include_directories()

功能:链接头文件

描述:可以将要链接的头文件都写在括号里,不用分成多个 INCLUDE_DIRECTORIES()写。

比如:

  • OpenCV3:${OpenCV_INCLUDE_DIRS}
  • ROS:${catkin_INCLUDE_DIRS}
include_directories(${OpenCV_INCLUDE_DIRS} ${catkin_INCLUDE_DIRS})

(9) ADD_EXECUTABLE()

ADD_EXECUTABLE(hello ${SRC_LIST})

生成可执行文件。

  • 相关的源文件是SRC_LIST 中 定义的源文件列表, 你也可以直接写成ADD_EXECUTABLE(hello main.c ti.c)

  • 可以写成 ADD_EXECUTABLE(hello main) cmake 会自动的在本目录查找 main.c 或者 main.cpp等,当然,最好不要偷这个懒,以免这个目录确实存在一个 main.c 和一个 main.cpp

  • hello是最终要执行的可执行文件:./hello

(10) TARGET_LINK_LIBRARIES()

TARGET_LINK_LIBRARIES(target library1 <debug | optimized> library2...)

功能:这个必须写ADD_EXECUTABLE() 之后,为生成文件target添加库。

比如:

  • OpenCV3:${OpenCV_LIBS}
  • ROS:${catkin_LIBRARIES}

3. 总结

添加文件的方式

  • 手动添加:set()

    SET(SRC_LIST "main.cpp forest.hpp")
    ADD_EXECUTABLE(main ${SRC_LIST})
    
  • 自动添加:AUX_SOURCE_DIRECTORY()

    AUX_SOURCE_DIRECTORY(. SRC_LIST)
    ADD_EXECUTABLE(main ${SRC_LIST})
    

四、构建OpenCV项目

项目结构

为了使整个项目更加条理,我们的文件夹采用如下组织方式:

bin
build
src
CMakeLists.txt

其中bin目录用于放编译生成的可执行文件,build目录用于cmake构建项目,src用于放源代码。

OpenCV源文件

下面是我们写的一个OpenCV示例代码:

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>using namespace std;
using namespace cv;int main(int argc, char** argv)
{if (argc != 2){cout << "Usage: opencv_test <image path>" << endl;return -1;}char *imgName = argv[1];Mat image;image = imread(imgName, 1);if (!image.data){cout << "No image data" << endl;return -1;}Mat gray_img;cvtColor(image, gray_img, CV_BGR2GRAY);imwrite("images/result.jpg", gray_img);return 0;
}

这是一个很简单的例子:读取图片然后转化成灰度图。

编写CMakeLists.txt

CMake文件的文件名CMakeLists.txt有严格的大小写要求,注意不要写错。

# project name
PROJECT(HELLO)# using C++11
set(CMAKE_CXX_FLAGS "${CAMKE_CXX_FLAGS} -std=c++11 ")# cmake version
CMAKE_MINIMUM_REQUIRED(VERSION 3.10)# find OpenCV
FIND_PACKAGE(OpenCV REQUIRED)# show the message of OpenCV
message(STATUS "OpenCV library status:")
message(STATUS "    version: 	${OpenCV_VERSION}")
message(STATUS "    headers: 	${OpenCV_INCLUDE_DIRS}")
message(STATUS "    libraries: 	${OpenCV_LIBS}")# link headers
INCLUDE_DIRECTORIES({OpenCV_INCLUDE_DIRS})# 添加源代码文件到SRC_LIST变量中
AUX_SOURCE_DIRECTORY(. SRC_LIST)# 生成可执行文件
ADD_EXECUTABLE(hello ${SRC_LIST})# after ADD_EXECUTABLE,为生成文件target添加库
TARGET_LINK_LIBRARIES(hello ${OpenCV_LIBS})

PROJECT指令的语法是:

PROJECT(projectname [CXX] [C] [Java])

你可以用这个指令定义工程名称,并可指定工程支持的语言,支持的语言列表是可以忽略的,这个指令隐式的定义了两个cmake变量: <projectname>_BINARY_DIR 以及<projectname>_SOURCE_DIR。前者指构建路径,后者指工程路径,即 CMakeLists.txt 所在的路径。

同时cmake系统也帮助我们预定义了 PROJECT_BINARY_DIRPROJECT_SOURCE_DIR 变量,他们的值分别跟 opencv_test_BINARY_DIRopencv_test_SOURCE_DIR 一致。

为了统一起见,建议以后直接使用 PROJECT_BINARY_DIRPROJECT_SOURCE_DIR,即使修改了工程名称,也不会影响这两个变量。如果使用了<projectname>_SOURCE_DIR,修改工程名称后,需要同时修改这些变量。

接下来是设置cmake要求的最低版本号:

cmake_minimum_required(VERSION 3.5)

SET指令的语法是:

SET(VAR [VALUE] [CACHE TYPE DOCSTRING [FORCE]])

现阶段,你只需要了解SET指令可以用来显式的定义变量即可。这里我们将变量CMAKE_RUNTIME_OUTPUT_DIRECTORY定义为${opencv_test_SOURCE_DIR}/bin也就是工程路径下的bin目录。

下面介绍一个很重要的指令:find_package 这个指令以被用来在系统中自动查找配置构建工程所需的程序库。在linux和unix类系统下这个命令尤其有用。CMake自带的模块文件里有大半是对各种常见开源库的 find_package 支持,支持库的种类非常多。

当它找到OpenCV程序库之后,就会帮助我们预定义几个变量,OpenCV_FOUNDOpenCV_INCLUDE_DIRSOpenCV_LIBRARY_DIRSOpenCV_LIBRARIES,它们分别指是否找到OpenCV,OpenCV的头文件目录,OpenCV的库文件目录,OpenCV的所有库文件列表。接着我们就可以使用这些变量来配置了:

include_directories(${OpenCV_INCLUDE_DIRS})

上面这个指令用来设置包含的头文件的路径。

link_directories(${OpenCV_LIBRARY_DIRS})

上面这个指令用来设置库文件的路径。

target_link_libraries(opencv_test ${OpenCV_LIBS})

上面这个指令用来设置需要的库文件,它的语法是:

TARGET_LINK_LIBRARIES(target library1<debug | optimized> library2...)

其中的target就是前面设置生成的目标文件(可执行文件):

add_executable(opencv_test src/opencv_test.cpp)

这个命令很好理解,首先是可执行文件的名字,然后是源码的名字。因此,这个命令一定要在TARGET_LINK_LIBRARIES之前使用。

现在我们的CMakeLists.txt就介绍完了。

构建项目并运行

mkdir build && cd build
cmake ..
make
# 至此构建完成,下面运行
./opencv_test

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/532566.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CVE-2017-7529Nginx越界读取缓存漏洞POC

漏洞影响 低危&#xff0c;造成信息泄露&#xff0c;暴露真实ip等 实验内容 漏洞原理 通过查看patch确定问题是由于对http header中range域处理不当造成&#xff0c;焦点在ngx_http_range_parse 函数中的循环&#xff1a; HTTP头部range域的内容大约为Range: bytes4096-81…

Linux命令行性能监控工具大全

Linux命令行性能监控工具大全 作者&#xff1a;Arnold Lu 原文&#xff1a;https://www.cnblogs.com/arnoldlu/p/9462221.html 关键词&#xff1a;top、perf、sar、ksar、mpstat、uptime、vmstat、pidstat、time、cpustat、munin、htop、glances、atop、nmon、pcp-gui、collect…

Weblogic12c T3 协议安全漏洞分析【CVE-2020-14645 CVE-2020-2883 CVE-2020-14645】

给个关注&#xff1f;宝儿&#xff01; 给个关注&#xff1f;宝儿&#xff01; 给个关注&#xff1f;宝儿&#xff01; 关注公众号&#xff1a;b1gpig信息安全&#xff0c;文章推送不错过 ## 前言 WebLogic是美国Oracle公司出品的一个application server,确切的说是一个基于JAV…

Getshell总结

按方式分类&#xff1a; 0x01注入getshell&#xff1a; 0x02 上传 getwebshell 0x03 RCE getshell 0x04 包含getwebshell 0x05 漏洞组合拳getshell 0x06 系统层getcmdshell 0x07 钓鱼 getcmdshell 0x08 cms后台getshell 0x09 红队shell竞争分析 0x01注入getshell&#xff1a;…

编写可靠bash脚本的一些技巧

编写可靠bash脚本的一些技巧 原作者&#xff1a;腾讯技术工程 原文链接&#xff1a;https://zhuanlan.zhihu.com/p/123989641 写过很多 bash 脚本的人都知道&#xff0c;bash 的坑不是一般的多。 其实 bash 本身并不是一个很严谨的语言&#xff0c;但是很多时候也不得不用。以下…

python 到 poc

0x01 特殊函数 0x02 模块 0x03 小工具开发记录 特殊函数 # -*- coding:utf-8 -*- #内容见POC.demo; POC.demo2 ;def add(x,y):axyprint(a)add(3,5) print(------------引入lambad版本&#xff1a;) add lambda x,y : xy print(add(3,5)) #lambda函数,在lambda函数后面直接…

protobuf版本常见问题

protobuf版本常见问题 许多软件都依赖 google 的 protobuf&#xff0c;我们很有可能在安装多个软件时重复安装了多个版本的 protobuf&#xff0c;它们之间很可能出现冲突并导致在后续的工作中出现版本不匹配之类的错误。本文将讨论笔者在使用 protobuf 中遇到的一些问题&#…

CMake常用命令整理

CMake常用命令整理 转自&#xff1a;https://zhuanlan.zhihu.com/p/315768216 CMake 是什么我就不用再多说什么了&#xff0c;相信大家都有接触才会看一篇文章。对于不太熟悉的开发人员可以把这篇文章当个查找手册。 1.CMake语法 1.1 指定cmake的最小版本 cmake_minimum_r…

CVE-2021-41773 CVE-2021-42013 Apache HTTPd最新RCE漏洞复现 目录穿越漏洞

给个关注&#xff1f;宝儿&#xff01; 给个关注&#xff1f;宝儿&#xff01; 给个关注&#xff1f;宝儿&#xff01; CVE-2021-41773漏洞描述&#xff1a; Apache HTTPd是Apache基金会开源的一款流行的HTTP服务器。2021年10月8日Apache HTTPd官方发布安全更新&#xff0c;披…

SSRF,以weblogic为案例

给个关注&#xff1f;宝儿&#xff01; 给个关注&#xff1f;宝儿&#xff01; 给个关注&#xff1f;宝儿&#xff01; 复习一下ssrf的原理及危害&#xff0c;并且以weblog的ssrf漏洞为案例 漏洞原理 SSRF(Server-side Request Forge, 服务端请求伪造) 通常用于控制web进而…

C++11 右值引用、移动语义、完美转发、万能引用

C11 右值引用、移动语义、完美转发、引用折叠、万能引用 转自&#xff1a;http://c.biancheng.net/ C中的左值和右值 右值引用可以从字面意思上理解&#xff0c;指的是以引用传递&#xff08;而非值传递&#xff09;的方式使用 C 右值。关于 C 引用&#xff0c;已经在《C引用…

C++11 std::function, std::bind, std::ref, std::cref

C11 std::function, std::bind, std::ref, std::cref 转自&#xff1a;http://www.jellythink.com/ std::function 看看这段代码 先来看看下面这两行代码&#xff1a; std::function<void(EventKeyboard::KeyCode, Event*)> onKeyPressed; std::function<void(Ev…

Java安全(一) : java类 | 反射

给个关注&#xff1f;宝儿&#xff01; 给个关注&#xff1f;宝儿&#xff01; 给个关注&#xff1f;宝儿&#xff01; 1.java基础 Java平台共分为三个主要版本Java SE&#xff08;Java Platform, Standard Edition&#xff0c;Java平台标准版&#xff09;、Java EE&#xff0…

LeetCode-287 寻找重复数 二分法

LeetCode-287 寻找重复数 二分法 287. 寻找重复数 给定一个包含 n 1 个整数的数组 nums &#xff0c;其数字都在 1 到 n 之间&#xff08;包括 1 和 n&#xff09;&#xff0c;可知至少存在一个重复的整数。 假设 nums 只有 一个重复的整数 &#xff0c;找出 这个重复的数 。…

对某公司一次弱口令到存储型xss挖掘

转自我的奇安信攻防社区文章:https://forum.butian.net/share/885 免责声明: 渗透过程为授权测试,所有漏洞均以提交相关平台,博客目的只为分享挖掘思路和知识传播** 涉及知识: xss注入及xss注入绕过 挖掘过程: 某次针对某目标信息搜集无意发现某工程公司的项目招标平台 …

C++11新特性选讲 语言部分 侯捷

C11新特性选讲 语言部分 侯捷 本课程分为两个部分&#xff1a;语言的部分和标准库的部分。只谈新特性&#xff0c;并且是选讲。 本文为语言部分笔记。 语言 Variadic Templatesmove semanticsautoRange-based for loopInitializer listLambdas… 标准库 type_traitsunodered…

java安全(二):JDBC|sql注入|预编译

给个关注&#xff1f;宝儿&#xff01; 给个关注&#xff1f;宝儿&#xff01; 给个关注&#xff1f;宝儿&#xff01; 1 JDBC基础 JDBC(Java Database Connectivity)是Java提供对数据库进行连接、操作的标准API。Java自身并不会去实现对数据库的连接、查询、更新等操作而是通…

java安全(三)RMI

给个关注&#xff1f;宝儿&#xff01; 给个关注&#xff1f;宝儿&#xff01; 给个关注&#xff1f;宝儿&#xff01; 1.RMI 是什么 RMI(Remote Method Invocation)即Java远程方法调用&#xff0c;RMI用于构建分布式应用程序&#xff0c;RMI实现了Java程序之间跨JVM的远程通信…

LeetCode-726 原子的数量 递归

LeetCode-726 原子的数量 递归 题目链接&#xff1a;LeetCode-726 原子的数量 给你一个字符串化学式 formula &#xff0c;返回 每种原子的数量 。 原子总是以一个大写字母开始&#xff0c;接着跟随 0 个或任意个小写字母&#xff0c;表示原子的名字。 如果数量大于 1&#xf…

java安全(四) JNDI

给个关注&#xff1f;宝儿&#xff01; 给个关注&#xff1f;宝儿&#xff01; 给个关注&#xff1f;宝儿&#xff01; 1.JNDI JNDI(Java Naming and Directory Interface)是Java提供的Java 命名和目录接口。通过调用JNDI的API应用程序可以定位资源和其他程序对象。JNDI是Java…