CMake入门实践(一) 什么是cmake

2023-11-17

一.CMake简介

CMake是一个跨平台的安装(编译)工具,可以用简单的语句来描述所有平台的安装(编译过程)。他能够输出各种各样的makefile或者project文件,能测试编译器所支持的C++特性,类似UNIX下的automake。只是 CMake 的组态档取名为 CMakeLists.txt。Cmake 并不直接建构出最终的软件,而是产生标准的建构档(如 Unix 的 Makefile 或 Windows Visual C++ 的projects/workspaces),然后再依一般的建构方式使用。这使得熟悉某个集成开发环境(IDE)的开发者可以用标准的方式建构他的软件,这种可以使用各平台的原生建构系统的能力是 CMake 和 SCons 等其他类似系统的区别之处。

cmake 的特点主要有:

  1. 开放源代码,使用类 BSD 许可发布。http://cmake.org/HTML/Copyright.html
  2. 跨平台,并可生成 native 编译配置文件,在 Linux/Unix 平台,生成 makefile,在苹果平台,可以生成 xcode,在 Windows 平台,可以生成 MSVC 的工程文件。
  3. 能够管理大型项目,KDE4 就是最好的证明。
  4. 简化编译构建过程和编译过程。Cmake 的工具链非常简单:cmake+make。
  5. 高效虑,按照 KDE 官方说法,CMake 构建 KDE4 的 kdelibs 要比使用 autotools 来构建 KDE3.5.6 的 kdelibs 快 40%,主要是因为 Cmake 在工具链中没有 libtool
  6. 可扩展,可以为 cmake 编写特定功能的模块,扩充 cmake 功能。

在 linux 平台下使用 CMake 生成 Makefile 并编译的流程如下:

  1. 编写 CMake 配置文件 CMakeLists.txt 。
  2. 执行命令 cmake PATH 或者 ccmake PATH 生成 Makefile。其中, PATH 是 CMakeLists.txt 所在的目录。
  3. 使用 make 命令进行编译。

二.Hello World

没有”Hello World”的教程不是好教程.这里首先举一个Hello world的例子给大家做一个对于CMake的感性理解.
详细的项目代码可以见: LearningCMake/HelloWorld/

比如我现在项目目录叫做HelloWorld,其中建立两个文件,分别是main.cppCMakeLists.txt(注意文件名大小写):

main.cpp文件中就是非常简单的输出Hello world的代码了,如下:

//main.cpp
#include <iostream>
int main() {
    std::cout << "Hello, World!" << std::endl;
    return 0;
}

CmakeLists.txt 文件内容:

cmake_minimum_required(VERSION 3.9)
project(HelloWorld)

set(CMAKE_CXX_STANDARD 11)

add_executable(HelloWorld main.cpp)

所有的文件创建完成后,HelloWorld目录中应该存在 main.cppCMakeLists.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/enningxie/xiekun/WorkSpace/LearningCMake/HelloWorld

再让我们看一下目录中的内容:
你会发现,系统自动生成了:CMakeFiles, CMakeCache.txt, cmake_install.cmake 等文件,并且生成了Makefile. 现在不需要理会这些文件的作用,以后你也可以不去理会。最关键的是,它自动生成了Makefile.

然后进行工程的实际构建,在这个目录输入make 命令,大概会得到如下的彩色输出:

Scanning dependencies of target HelloWorld
[ 50%] Building CXX object CMakeFiles/HelloWorld.dir/main.cpp.o
[100%] Linking CXX executable HelloWorld
[100%] Built target HelloWorld

如果你需要看到 make 构建的详细过程,可以使用 make VERBOSE=1 来进行构建。
这时候,我们需要的目标文件 HelloWorld已经构建完成,位于当前目录,尝试运行一下:
./HelloWorld得到输出:

Hello,World!

三.基本用法解释

上面用一个非常简单的HelloWorld例子简单介绍了构建使用cmake构建项目的完整过程.但是其中还有很多地方新手可能不是很理解.比如CMake怎么使用. CMakeList.txt 里面到底是一些什么东西等等. 这部分就来讲一下上面那个简单的项目到底用了一些什么东西.更加复杂的以后再讲到,这里确保把最基本的一些给理清楚.

重新看一下 CMakeLists.txt,这个文件是 cmake 的构建定义文件,文件名
是大小写相关的,如果工程存在多个目录,需要确保每个要管理的目录都存在一个
CMakeLists.txt。(关于多目录构建,后面我们会提到,这里不作过多解释)。

上面例子中的 CMakeLists.txt 文件内容如下:

cmake_minimum_required(VERSION 3.9)

project(HelloWorld)

set(CMAKE_CXX_STANDARD 11)

add_executable(HelloWorld main.cpp)

先看第一行cmake_minimum_required(VERSION 3.9),这行看意思都能够直接看出来了,表示指定运行此配置文件所需的 CMake 的最低版本;所以看到其他的CMakeList文件没有写这个也是正常的.但是还是推荐写,是因为避免引起cmake不同版本之间构建错误的问题.

然后看第二行,project(HelloWorld) 该命令指定项目的名称,比如这里的项目名称为HelloWorld.更加详细的来说, project 指令的语法是:

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

你可以用这个指令定义工程名称,并可指定工程支持的语言,支持的语言列表是可以忽略的,
默认情况表示支持所有语言。所以我们常见使用的时候,就直接使用project(projectname) 就够了. 这个指令隐式的定义了两个 cmake 变量:
_BINARY_DIR 以及_SOURCE_DIR,这里就是
HelloWorld_BINARY_DIRHelloWorld_SOURCE_DIR.
因为采用的是内部编译,两个变量目前指的都是工程所在路径LearningCMake/HelloWorld/,后面我们会讲到外部编译,两者所指代的内容会有所不同。

同时 cmake 系统也帮助我们预定义了 PROJECT_BINARY_DIRPROJECT_SOURCE_DIR变量,他们的值分别跟 HelloWorld_BINARY_DIRHelloWorld_SOURCE_DIR 一致。 为了统一起见,建议以后直接使用 PROJECT_BINARY_DIRPROJECT_SOURCE_DIR,即
使修改了工程名称,也不会影响这两个变量。如果使用了
<projectname>_SOURCE_DIR,修改工程名称后,需要同时修改这些变量。

然后来看第三行set(CMAKE_CXX_STANDARD 11) 这里是把之后的编译选项设置为了C++ 11,

set 指令的语法是:

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

现阶段,你只需要了解 set 指令可以用来显式的定义变量即可。
比如我们用到的是 set(SRC_LIST main.c),如果有多个源文件,也可以定义成:
set(SRC_LIST main.c t1.c t2.c)

然后我们来看最后一行add_executable(HelloWorld main.cpp),这行的作用就是将名为 main.cpp 的源文件编译成一个名称为 HelloWorld 的可执行文件。同样的,更加详细的用法如下:

add_executable(executable_name ${SRC_LIST})

定义了这个工程会生成一个文件名为 executable_name 的可执行文件,相关的源文件是 SRC_LIST
定义的源文件列表.

四.内部构建和外部构建

内部构建和外部构建这个词这么装逼,其实实际上面非常简单,别被吓到.

通俗一点,内部构建就是在项目内部,有CMakeList.txt的地方,直接cmake .,比如我们前面讲的简单案例都是最简单的内部构建. 结果你也看见了,就是在项目下面生成了很多的临时文件.

外部构建就是不直接在项目下面运行cmake, 而是自己建立一个接受cmake之后的临时文件的文件夹,然后再该文件夹下面调用cmake <CMakeList_path> 来构建.运行 make 构建工程,就会在当前目录(build 目录)中获得目标文件 hello。上述过程就是所谓的out-of-source外部编译,一个最大的好处是,对于原有的工程没有任何影响,所有动作全部发生在编译目录。

有编译过OpenCV或者其他类似项目的童鞋,都应该知道,编译OpenCV的时候,我们常常自己建立一个build目录,然后在该目录下面运行cmake,最终临时文件就会在这个目录下面生成.

这里直接举一个例子,完整项目代码:LearningCMake/4.HelloWorld4/

这里代码结构和CMakeList.txt都和第一个最简单的是差不多的.但是这里有一个不同,就是在里面建立了一个build文件夹.然后再build文件夹里面运行cmake ..,结果就是之前的临时文件都存放在了这个build文件夹里面,同时在这个文件夹里面直接make可以得到最终的可执行文件.

到了这里,结合CMakeList.txt文件中每个命令语句和生成执行文件的详细步骤.你应该对于cmake的运作过程有了一个基本的了解.当然这并不等于全部,有了这些基础,后面慢慢介绍更多更加常用的用法.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

CMake入门实践(一) 什么是cmake 的相关文章

随机推荐

  • 【易售小程序项目】小程序首页(展示商品、商品搜索、商品分类搜索)【后端基于若依管理系统开发】

    文章目录 界面效果 界面实现 工具js 页面 首页 让文字只显示两行 路由跳转传递对象 将商品分为两列显示 使用中划线划掉原价 后端 商品 controller service mapper sql 同项目其他文章 界面效果 说明 界面中商
  • Docker容器中如何运行一个带GUI的app?

    问 How can you run GUI apps in a docker container Are there any images that set up vncserver or something so that you can
  • 图像处理之-----插值算法

    插值算法是图像处理中最基本的算法 首先我们先了解一下什么是插值算法 以及插值算法在图像处理过程中的应用 1 什么是插值 Interpolation is a method of constructing new data points wi
  • Redis 密码设置和查看密码

    Redis 密码设置和查看密码 redis没有实现访问控制这个功能 但是它提供了一个轻量级的认证方式 可以编辑redis conf配置来启用认证 1 初始化Redis密码 在配置文件中有个参数 requirepass 这个就是配置redis
  • Python软件开发之需求实现:数据结构、数据类型。自动化软件测试必会

    一 有这样的一个需求 判断学生成绩是否及格 二 拿到这样的一个需求如何进行需求分析呢 做为测试人员 我们只有明确需求后 才不容易漏测 需求分析阶段 一 看到这样的一句话之后我们有几个问题需求和产品经理确认的 1 什么样的算及格 60 70分
  • Spark 启动集群 Master 正常启动 Worker 不启动

    在学习spark过程中遇到的问题 做下记录 这个问题网上出现的不再少数 出现问题的原因也是各不相同 并且没有一个人的问题和我完全一样 我高兴得都快哭了 顺着大家的思路 尝试了两个多小时才搞明白 问题的根源大多都在于 hostname 的配置
  • C++ STL - vector 模拟实现+解析迭代器

    目录 vector使用 vector模拟实现 vector实现解析 memcpy进行元素拷贝问题 扩容问题 vector迭代器解析 vector迭代器失效问题 1 示例一 一个典型的迭代器失效bug insert实现 2 示例二 inser
  • 记录一些可能会用到资料

    1 win11子系统WSL修改用户密码 以管理员身份打开 PowerShell 输入命令 wsl exe user root passwd root 修改 root 用户密码 2 layDate控件在页面高度不够的情况下闪退 在laydat
  • 8x8LED点阵

    点量这个只需要把9高电平 13低电平就可以了 共阳极点阵 行线是led的正极 列线是led的列线 左上角点亮 显示多个灯是动态扫描的 一个一个显示的 然后间隔速度要快就可以造成显示 点阵由两篇74Hc595级联在一起驱动的 只需要三个io口
  • matplotlib输出图形到网页_Python实操:手把手教你用Matplotlib把数据画出来

    导读 获取数据之后 而不知道如何查看数据 用途还是有限的 幸好 我们有Matplotlib Matplotlib 是基于 NumPy 数组构建的多平台数据可视化库 它是John Hunter 在2002年构想的 原本的设计是给 IPytho
  • 【LeetCode与《代码随想录》】哈希表篇:做题笔记与总结-JavaScript版

    文章目录 代码随想录 主要题目 242 有效的字母异位词 349 两个数组的交集 202 快乐数 1 两数之和 经典哈希 454 四数相加 II 15 三数之和 双指针 18 四数之和 双指针 相关题目 383 赎金信 49 字母异位词分组
  • mnist数据集之自己写的数字

    这是我自己用画图3D写的数字0 9 然后又把它们修改成了28 28像素的格式 并经过测试后输出了预测值 不知道怎么搞得 顺序打乱了 这是我测试后的结果 要加油哦
  • C语言——执行创建多个文件同时写入内容

    代码 include
  • Python3, 多种方法实现文件/目录的监听,只想说一个字:泰裤辣。

    多种方法实现文件 目录监听 1 引言 2 代码实战 2 1 os模块 2 2 watchdog库 2 2 1 安装 2 2 2 示例 2 3 inotify 2 3 1 安装 2 3 2 示例 3 总结 1 引言 小屌丝 鱼哥 帮我看下这段
  • 说透 Nacos 一致性协议

    1 Nacos 致性协议 1 1 为什么 Nacos 需要 致性协议 Nacos尽可能减少用户部署以及运维成本 做到用户只需要 个程序包 就快速单机模式启动 Nacos 或集群模式启动 Nacos 而 Nacos 是 个需要存储数据的组件
  • java基础—HashMap实现原理,如何保证HashMap的线程安全

    在多线程条件下 容易导致死循环 具体表现为CPU使用率100 因此多线程环境下保证 HashMap 的线程安全性 主要有如下几种方法 1 替换成Hashtable Hashtable通过对整个表上锁实现线程安全 因此效率比较低 2 使用Co
  • 台式计算机的配置怎么看,台式电脑配置怎么看

    电脑的性能 价格决定于电脑的配置 很多人电脑新手在购买电脑的时候对电脑配置的相关情况不太了解 导致新买的电脑频频出问题 所以了解自己电脑配置是很重要的 这里我们就简单的来说说台式电脑配置怎么看 电脑配置一般CPU 显卡 主板 内存 硬盘 显
  • lambda表达式二之Stream流

    Stream流 是数据渠道 用于操作数据源 集合 数组等 所生成的元素序列 集合讲的是数据 流讲的是计算 Stream自己不会存储元素 Stream不会改变源对象 会返回一个持有结果的新Stream Stream操作是延迟执行的 意味着会等
  • LeetCode312. 戳气球 (分治,记忆化搜索,动态规划)

    LeetCode312 戳气球 解题思路 记忆化搜索 动态规划 解题思路 官方题解 参考题解 核心思想 由于戳气球的操作会导致两个气球从不相邻变成相邻 使得后续操作难以处理 于是我们倒过来看这些操作 将全过程看成每次添加一个气球 solve
  • CMake入门实践(一) 什么是cmake

    一 CMake简介 CMake是一个跨平台的安装 编译 工具 可以用简单的语句来描述所有平台的安装 编译过程 他能够输出各种各样的makefile或者project文件 能测试编译器所支持的C 特性 类似UNIX下的automake 只是