什么是 CMake?
CMake 是一个跨平台的编译构建工具,用来自动化生成 Makefile 之类的构建文件的。

一般在 unix 类系统上开发,我们用 gcc 或者 g++ 编译源码。

g++ hello.cpp  world.cpp

对很小的工程,处理的源码文件就这么几个,我们完全手写编译脚步就好了。
但是如果工程量变大,情况就变得复杂了,我们就需要用 make 工具,并编写 Makefile 记录好源码与依赖之间的关系。
make 配合 Makefile 使用,威力很大,但是手写代码很烦恼,而 cmake 似乎更现代化,它能够自动生成 Makefile,并且逻辑似乎更清晰。
你可以简单地认为,cmake 的使用比手写 Makefile 更简单。
当然,我并不是说 cmake 比 make 更高级,更好,只是相对于新手而言,它是很友好的,我们都希望把精力花在编写具体的业务代码上,而不是炫技一般编写复杂的 Makefile 文件,我决定学习 CMake 也是看到 OpenCV 改用它编译了,另外 Android 的源码好像也是它,这也让我不得不去学习它。
至于 CMake 和其它编译工具孰好孰坏,这里我不做评价。

一个最简单的 CMake 例子
要构建一个 CMake 编译系统,首先需要在代码根目录创建一个 CMakeLists.txt 文件,这个文件是用来描述构建过程的,可以看做是一个高级版的 Makefile 文件。

假设整个工程只有 hello.cpp 这个文件.

#include <iostream>using namespace std;int main(int argc,char** argv)
{cout << "Hello for cmake!" << endl;return 0;
}

如果要编译的话,我们可以这样编写 CMakeLists.txt 。

cmake_minimum_required(VERSION 2.8.11)
project(HELLO)
add_executable(hello hello.cpp)

3 行代码就搞定了。

cmake_minimum_required()这句代码是指定 cmake 的最低版本
project()这句代码是指定工程的名称
add_executable()这个指示生成的可执行文件,上面的例子是编译 hello.cpp 生成 hello 这个可执行文件

CMakeLists.txt 写好后,在当前目录执行 cmake .命令,.代表在当前目录执行操作,如果 CMakeLists.txt 在别处,需要将路径添加在 cmake 后面。

-- The C compiler identification is GNU 5.4.0
-- The CXX compiler identification is GNU 5.4.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/frank/exercises/cmake

命令完成后,我们可以发现当前目录多了 1 个名为 CMakeFiles 的文件,也多了一个 Makefile 文件。
我们再执行 make 命令,最终可以发现生成了可执行文件 hello.

[ 50%] Building CXX object CMakeFiles/hello.dir/hello.cpp.o
[100%] Linking CXX executable hello
[100%] Built target hello

在终端执行 ./hello,可以看见屏幕打印了

Hello fo cmake!

正式 hello.cpp 中的输出。

这是最简单的 cmake 编译例子,但实际工作中是不会有这么简单的,实际工作中会涉及到很多的源文件,还有很多的动态的库,静态的库。

下面讲解一个稍微复杂但完整的例子。

一个稍微复杂的 CMake 例子
假设 hello.cpp 需要调用一个 so 中的 api,这个 so 库是由 world.cpp 编译生成的。

这个应该可以代表大多数开发场景,因为 C/C++ 工程开发中,避免不了要调用其他的 so 或者是 .a 文件,也要和 .h 头文件打交道。

#ifndef __WORLD_H__
#define __WORLD_H__void say_hello();#endif

上面是 world.h 的代码,它位于工程中 ./include文件夹。

#include <iostream>
#include "include/world.h"void say_hello()
{std::cout << "I\'m frank909! blog is frank909.blog.csdn.net." << std::endl;
}

上面是 world.cpp 的代码。

#include <iostream>
#include "include/world.h"using namespace std;
int main(int argc,char** argv)
{cout << "Hello for cmake!" << endl;say_hello();return 0;
}

上面是 hello.cpp 修改后的代码,它直接调用了 say_hello()方法,这个时候我们需要仔细考虑怎么写 CMakeLists.txt 文件了。

cmake_minimum_required(VERSION 2.8.11)
project(HELLO)include_directories("include")
add_library(world world.cpp)add_executable(hello hello.cpp)
target_link_libraries(hello world)

include_directories()这句代码指定了头文件地址
add_library()的作用是生成库文件,默认是 .a 的文件,也就是静态库,如何生成动态库接下来的部分会讲。
target_lingk_libraries()这句代码的意思也很容易懂,那就是为可执行文件 hello 链接 libworld.a 这个库。
执行 cmake .操作可以看到会正常生成 MakeFile 文件。
再执行 make动作,可以看见目标正常生成。

Scanning dependencies of target world
[ 25%] Building CXX object CMakeFiles/world.dir/world.cpp.o
[ 50%] Linking CXX static library libworld.a
[ 50%] Built target world
Scanning dependencies of target hello
[ 75%] Building CXX object CMakeFiles/hello.dir/hello.cpp.o
[100%] Linking CXX executable hello
[100%] Built target hello

生成了两个文件 libworld.a 和 hello.
我们执行 ./hello 可以看到如下结果。

Hello for cmake!
I'm frank909! blog is frank909.blog.csdn.net.

以上的例子就基本覆盖了我们日常开发的模式。
指定头文件路径
指定动态库或者是静态库的路径,然后链接。
我们已经具备自己编写简单的 CMakeLists.txt 的能力了,但为了更好的理解和灵活运用我们还需要学习一些关于 cmake 的基本概念。
cmake 中的 target
cmake 的主要工作大多是为了操作各种各样的 target,cmake 把二进制可执行文件和库都称为 target。
target 就是指 cmake 要编译的目标。
可执行文件
add_executable()指定了可执行文件,它是 unix 上 a.out 之类的文件和 windows 平台 .exe 文件

动态库和静态库都使用 add_library()命令生成,也就是 unix 平台上的 .so 和 .a 文件,window 上的 .DLL 文件等等。
add_library()默认生成 .a 文件,如果要生成 .so 文件用
add_library(test SHARED test.cpp)这样的形式,要指定 SHARED 模型,才会生成 libtest.so 文件。
默认的效果等同于
add_library(test STATIC test.cpp)生成的是 libtest.a 文件。
链接库
link_libraries(hello test)cmake 通过 link_libraries() 命令指定了目标间的依赖关系,示例代码中 hello 是可执行文件,test 是库。
指定头文件
include_directories()指定了编译系统的头文件地址
处理好了头文件、库的生成和链接、可执行文件的生成,cmake 就基本 OK 了。
如果,遇到更复杂的情况的话,还是需要深入了解 CMake 构建机制,我就陆续编写更详细的内容。

备注:
点击下面链接,进入奥比中光开发者社区,了解更多3D视觉技术信息:https://developer.orbbec.com.cn/
或扫描下方二维码,进入奥比中光开发者社区:

深入浅出CMake(一):基础篇相关推荐

  1. 深入浅出CMake(二): 基础语法

    在<深入浅出CMake(一):基础篇>文章中,我们已经知道了怎么依葫芦画瓢编写简单的 CMake 构建文件了,但如果应对复杂的工程的话,这还是远远不够的. CMake 是一套编译构建体系, ...

  2. linux opencv cmake,OpenCV基础篇之使用CMake管理工程

    OpenCV基础篇之使用CMake管理工程 程序及分析 /* * FileName : read.cpp * Author  : xiahouzuoxin @163.com * Version  : ...

  3. 深入浅出程序设计竞赛 - 基础篇_Re: 从零开始的程序设计竞赛(三)

    Re: 从零开始的程序设计竞赛顾名思义,是一个力图介绍完全没有接触过程序设计竞赛的学校.老师及学生进入比赛的文章.文章包含如何参加比赛以及训练如何安排等内容.你可以查看过往的几期内容: Re: 从零开 ...

  4. 学习C++:C++进阶(三)CMake基础篇---用一个小型项目了解CMake及环境构建

    V1.1 于2022年7月15日第二次修改:添加了比较多的解释图,解读了各类库的CMakelist.txt文件 目录 第一部分 基础篇(Basics) 1.0 本部分主要学什么(Intro) 1.1 ...

  5. 深入浅出Mysql - 基础篇(列类型/运算符/函数)

    深入浅出Mysql - 基础篇(列类型/运算符/函数) 每一个常量.变量和参数都有数据类型,它用来指定一定的存储格式.约束和有效范围.MySQL提供了多种数据类型,主要包括数值型.字符串类型.日期和时 ...

  6. Android事件分发机制:基础篇:最全面、最易懂

    如何提升安卓水平?安卓开发者必须了解的事件分发机制. 最全面.最易懂的形式来讲解Android事件分发机制. 0. 前言 鉴于安卓分发机制较为复杂,故分为多个层次进行讲解,分别为基础篇.实践篇与高级篇 ...

  7. java综合知识点总结基础篇

    一.JDK常用的包 java.lang: 这个是系统的基础类,比如String.Math.Integer.System和Thread,提供常用功能. java.io: 这里面是所有输入输出有关的类,比 ...

  8. 最全MySQL基础篇

    文章目录 导入表的问题 第三章_最基本的SELECT语句 1. SQL语言的规则和规范 1) 基本规则 2) SQL大小写规范(建议遵守) 3) 注释 4) 命名规则 2. 基本的SELECT语句 1 ...

  9. 基于c++和asio的网络编程框架asio2教程基础篇:1、基本概念和使用说明

    基于c++和asio的网络编程框架asio2教程基础篇:1.基本概念和使用说明 由于asio2没有写技术文档,因此打算写几篇文章介绍一下如何使用它,主要是针对新手. 1.asio2如何使用? asio ...

  10. 视频教程-Linux系列课程(基础篇)-Linux

    Linux系列课程(基础篇) 2年JavaEE开发 ,5年资深大数据开发大牛,曾就职于蓝点科技,擅长精准广告系统开发,精通Linux操作系统! 具备丰富的大数据研发和培训经验,熟练运用Hadoop和S ...

最新文章

  1. 主机配置_分享几套电脑主机配置
  2. 虚拟和现实,两种不同身份的切换——留美95后的游戏人生
  3. 多个asp.net程序共用Session(sso程序的外设接口)
  4. location 拦截所有_让它帮你干掉所有流氓软件,还你一个清静系统
  5. 王传福凭啥“抛弃”燃油车?
  6. mybatis mapper配置 bigint_Mybatis-Plus入门
  7. azure备份存储层分类_备份到Azure –如何做到这一点?
  8. DSO(Direct Sparse Odometry)
  9. WordPress简约mkBlog博客主题模板v2.1
  10. MATLAB代码美化器
  11. 离散数据:析取范式与合取范式
  12. 软件测试女生可以学习么?现在还能入行么?
  13. 工具系列 | FPM进程管理器详解
  14. AutoIT - 加域工具
  15. Solidity动态数组汇编开发教程
  16. 抓网页_面包网_javaSE
  17. 5V单端差分信号编码器转脉冲24V电平集电极开路变送器
  18. Transformer25
  19. 微核Linux(Tiny Core Linux)
  20. 【招商银行数据方向笔试题】—— 信用卡推荐客户列表

热门文章

  1. 网站统计中的PV(访问量):UV(独立访客):IP(独立IP)的定义与区别
  2. 硅谷产品实战-总结:14、如何用数据做出产品决定?
  3. 高效排序算法(快排序)
  4. 短视频个性化Push工程精进之路
  5. 《让系统发生重大宕机事故的15个方法》
  6. 为什么很多SpringBoot开发者放弃了Tomcat,选择了Undertow?
  7. 本地缓存性能之王Caffeine
  8. 从 Nginx 优秀的核心架构设计,揭秘其为何能支持高并发?
  9. 边缘计算的三种模式:MEC、微云和雾计算
  10. Iaas、Caas、Paas、Faas!选择正确的平台!