cmake 入门笔记

1. cmake 是什么?

这些年大型 C/C++ 工程都纷纷转到了 cmake 环境下,那么这个工具到底有什么魅力吸引着大家呢?无它,软件工程崇尚实用主义,而 cmake 的功能强悍而灵活,趁手的工具用起来!为了从 makefile 下解放大伙的双手, cmake 在设计之初的目标就是奔着用于对程序构建过程进行管理,它会自动对工程生成相应的 makefile 和其它辅助构建信息。

注意: cmake 不是编译器,仅是构建管理工具,比如调度编译器/链接器等等

2. cmake 的配置文件 CMakeLists.txt

使用 cmake 来构建工程成功输出目标文件,这个过程需要依赖于配置的设定。而这个设定存放在文件 CMakeLists.txt 中,每个构建工程都至少有一个这样的文件(如果工程有子工程,那么每个子工程又会有对应的配置文件),该文件可按需定制。一般会在工程的根目录下创建这个文件 CMakeLists.txt。举个栗子,这里有个最简单的配置示例(假设本工程不包含子工程,只有一个源文件 main.cpp 而且存放于工程根目录下):

指定最低要求的 cmake 版本 3.10
cmake_minimum_required(VERSION 3.10)

设置工程名 test
project(test)

指定编译输出可执行结果文件 test, 指定编译源文件 main.cpp
add_executable(test main.cpp)

当然,除了把配置内容写在配置文件 CMakeLists.txt 中,还可以在执行 cmake 指令时传入多样化的参数,不过通过传参的方式用起来不灵活而且不利于持续输出的开发理念。同一套产品输出给不同的客户时,可以将不同客户的需求转化为不同的配置文件,分别调用于构建目标结果文件。

3. CMakeLists.txt 变量

CMakeLists.txt 文件内部同样支持变量,包括变量定义和引用等。

eg. 定义变量 USE_CUSTOM_SRC,并设置默认值 OFF (如果引用该变量前,没有赋值,那么当前值为默认值):

option (USE_CUSTOM_SRC "something you want to mark" OFF)

或者只是定义变量 USE_CUSTOM_SRC,并赋值 true

SET(USE_CUSTOM_SRC true)

或者通过调用其它程序并接收输出值,跳过定义,如在调用变量 CMAKE_CURRENT_SOURCE_DIR 代表的目录下执行程序 git 带上参数 "log --format='%h' -1" 以获取 SHA1 值并且保存到变量 GIT_SHA1 中。

exec_program(
        "git"
        ${CMAKE_CURRENT_SOURCE_DIR}
        ARGS "log --format='%h' -1"
        OUTPUT_VARIABLE GIT_SHA1
    )

在调用 cmake 时同样可以在传入的参数中指定变量 USE_CUSTOM_SRC 并赋值,变量前加 -D,如:

cmake -DUSE_CUSTOM_SRC=ON

CMakeLists.txt 中,已定义的变量可直接引用:

if(USE_CUSTOM_SRC)
    xxx
else()
    xxx
endif()

4. CMakeLists.txt 定义源码相关的宏定义

如果需要为源码编译器添加宏定义呢?
如下:

add_definitions(-DUSE_CUSTOM_SRC)

这段语句定义了适用于源代码中的预编译宏 USE_CUSTOM_SRC, 以 -D 为前缀。
注意:这里的 USE_CUSTOM_SRC (适用范围是被 cmake 管理的工程源代码) 与上面的 CMakeLists.txt 变量 USE_CUSTOM_SRC (适用范围是 cmake 读取的 CMakeLists.txt 文件内容内) 不一样

5. 执行方法

先说一下我的环境:

WIN10 + WSL Ubuntu 18.4

wsl 环境下要求安装有cmake、gcc、g++ 等基本工具。

首先进入 wsl 环境,看一下当前的工作目录内容:

admin@DESKTOP:/mnt/g/test$ ls -l
total 0
-rwxrwxrwx 1 root root  89 Jun 26 16:12 CMakeLists.txt
-rwxrwxrwx 1 root root 354 Jun 26 17:13 main.cpp

源文件 main.cpp 实现了执行指令 ls -l . 的功能,下面是文件内容

#include <unistd.h>
#include <stdio.h>

int main()
{
    pid_t pid = fork();
    if (pid == -1) {
        perror("fork error");
    }

    if (pid == 0) {
        execl("/bin/ls", "ls", "-l", ".", (char *)NULL);
    }

    return 0;
}
</stdio.h></unistd.h>

创建构建输出目录 build,然后导航到输出目录

mkdir build
cd build

执行 cmake,输入参数是存放 CMakeLists.txt 文件的相对目录,目的是配置构建工程和生成用于原生构建的必需信息并保存到当前目录文件中,也就是所谓的配置构建系统

admin@DESKTOP:/mnt/g/test/build$ cmake ../
-- The C compiler identification is GNU 7.5.0
-- The CXX compiler identification is GNU 7.5.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: /mnt/g/test/build

再次执行 cmake,调用当前目录的构建系统实现项目构建,包括编译/链接和输出二进制目标文件。

admin@DESKTOP:/mnt/g/test/build$ cmake --build .
Scanning dependencies of target test
[ 50%] Building CXX object CMakeFiles/test.dir/main.cpp.o
[100%] Linking CXX executable test
[100%] Built target test

这一步的操作其实也可以直接调用 make实现,比如需要用到加速的选项 -j等就比较推荐这样子调用

make -jn

看一下输出的二进制目标文件是否存在

admin@DESKTOP:/mnt/g/test/build$ ls -l
total 40
-rwxrwxrwx 1 root root 12704 Jul 12 21:34 CMakeCache.txt
drwxrwxrwx 1 root root   512 Jul 12 21:39 CMakeFiles
-rwxrwxrwx 1 root root  4847 Jul 12 21:34 Makefile
-rwxrwxrwx 1 root root  1552 Jul 12 21:34 cmake_install.cmake
-rwxrwxrwx 1 root root  8392 Jul 12 21:39 test

最后执行一下目标文件,看看实际执行结果和代码的意图是否一致

admin@DESKTOP:/mnt/g/test/build$ ./test
total 40
-rwxrwxrwx 1 root root 12704 Jul 12 21:34 CMakeCache.txt
drwxrwxrwx 1 root root   512 Jul 12 21:39 CMakeFiles
-rwxrwxrwx 1 root root  4847 Jul 12 21:34 Makefile
-rwxrwxrwx 1 root root  1552 Jul 12 21:34 cmake_install.cmake
-rwxrwxrwx 1 root root  8392 Jul 12 21:39 test

好了,简简单单介绍到这里,欢迎留言交流_

Original: https://www.cnblogs.com/englyf/p/16667896.html
Author: englyf八戒
Title: cmake 入门笔记

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/574062/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 我叫Mongo,干了「索引探索篇」提升我的效率,值得您拥有

    这是mongo第四篇”索引探索”,后续会连续更新4篇 mongodb的文章总结上会有一系列的文章,顺序是先学会怎么用,在学会怎么用好,戒急戒躁,循序渐进,跟…

    Linux 2023年6月14日
    082
  • Docker基本命令

    第一次使用docker,从helle world开始 docker run hello-world 镜像的完整写法:[仓库地址/]镜像名[:版本号] –help 查看帮…

    Linux 2023年6月13日
    0111
  • 好记性不如烂笔头系列之STM32 SysTick 精确延时(非中断方式)

    在stm32里,如果想精确延时又不需要中断做别的事; 就可以选择这个stick延时方法,简单易用。其寄存器容易设置,如下图 寄存器一目了然, 就是有一点 其记数只有24位,所以最大…

    Linux 2023年6月13日
    0123
  • pysimpleGui 之table使用

    (class) Table(values, headings=None, visible_column_map=None, col_widths=None, def_col_wid…

    Linux 2023年6月14日
    098
  • 如何配置VLAN

    一、vlan的概念与作用 首先,在学习如何配置vlan时我们先要了解一下为什么要配置vlan?vlan在平常的工作中有什么作用? vlan:虚拟的划分网段 即虚拟网络,在平常的工作…

    Linux 2023年6月6日
    0164
  • linux中软件的安装方式

    linux中软件的安装方式 四种方式 ​ 源码编译安装 ​ rpm安装 ​ yum安装 解压、配置(hadoop、hive等) 1.源码编译安装 1.为了编译nginx源码 yum…

    Linux 2023年6月11日
    096
  • 灵敏度分析简介

    参考文章1 😄参考文章2 😸参考文章3 😃 1. 灵敏度分析: 某一个假定的常量,在现实中不可能完全保持不变,可能发生一定范围的波动。灵敏度分析就是检验这部分波动对结果的影响。 灵…

    Linux 2023年6月14日
    0111
  • Celery异步任务

    情景: 用户发起request,并等待response返回。在本些views中,可能需要执行一段耗时的程序,那么用户就会等待很长时间,造成不好的用户体验,比如发送邮件、手机验证码等…

    Linux 2023年6月8日
    091
  • Redis深入浅出

    bash;gutter:true; RDB持久化是指在指定的时间间隔内将内存中的数据集快照写入磁盘,实际操作过程是fork一个子进程,先将数据集写入临时文件,写入成功后,再替换之前…

    Linux 2023年5月28日
    0112
  • 聊聊消息中心的设计与实现逻辑

    厌烦被消息打扰,又怕突然间的安静; 一、业务背景 微服务的架构体系中,会存在很多基础服务,提供一些大部分服务都可能需要的能力,比如文件管理、MQ队列、缓存机制、消息中心等等,这些服…

    Linux 2023年6月14日
    095
  • 学习一下 JVM (二) — 学习一下 JVM 中对象、String 相关知识

    一、JDK 8 版本下 JVM 对象的分配、布局、访问(简单了解下) 1、对象的创建过程 (1)前言Java 是一门面向对象的编程语言,程序运行过程中在任意时刻都可能有对象被创建。…

    Linux 2023年6月11日
    0114
  • 安装及管理文件

    优点: 契合系统兼容性强 如果你可以看懂源代码,修改新增功能 比较自由 缺点: 如果编译出了问题,你看不懂源代码,无法解决 安装过程复杂 没有统一的管理人员 安装过程 程序包编译安…

    Linux 2023年6月6日
    0106
  • ffmpeg 格式转换

    1.学前知识 1.1视频码率值 码率公式: 码率(kbps)=文件大小(KB)*8/时间(秒) 所以码率和视频文件大小成正比的,不过码率超过一定值后,人眼是看不出效果的. 接下来,…

    Linux 2023年6月7日
    0136
  • Cisco 7200 路由 PPPOE 拨号详解

    R1(config)#vpdn enable #启用vpdn虚拟专用拨号网络 R1(config)#interface dialer 1 #定义拨号器1 R1(config-if)…

    Linux 2023年6月6日
    096
  • 分布式系统中数据存储方案实践

    数据膨胀的时候,必然放大细节。 一、背景简介 在项目研发的过程中,对于数据存储能力的依赖无处不在,项目初期,相比系统层面的组件选型与框架设计,由于数据体量不大,在存储管理方面通常容…

    Linux 2023年6月14日
    088
  • 服务器部署 Vue 和 Django 项目的全记录

    本篇记录我在一个全新服务器上部署 Vue 和 Django 前后端项目的全过程,内容包括服务器初始配置、安装 Django 虚拟环境、python web 服务器 uWSGI 和反…

    Linux 2023年6月7日
    0119
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球