CMake学习(上)

1. CMake概述

CMake 是一个项目构建工具,并且是跨平台的。关于项目构建我们所熟知的还有Makefile(通过 make 命令进行项目的构建),大多是IDE软件都集成了make,比如:VS 的 nmake、linux 下的 GNU make、Qt 的 qmake等,如果自己动手写 makefile,会发现,makefile 通常依赖于当前的编译平台,而且编写 makefile 的工作量比较大,解决依赖关系时也容易出错。

而 CMake 恰好能解决上述问题, 其允许开发者指定整个工程的编译流程,在根据编译平台,自动生成本地化的Makefile和工程文件,最后用户只需make编译即可,所以可以把CMake看成一款自动生成 Makefile的工具,其编译流程如下图:

image-20230309130644912

  • 蓝色虚线表示使用makefile构建项目的过程
  • 红色实线表示使用cmake构建项目的过程

介绍完CMake的作用之后,再来总结一下它的优点:

  • 跨平台
  • 能够管理大型项目
  • 简化编译构建过程和编译过程
  • 可扩展:可以为 cmake 编写特定功能的模块,扩充 cmake 功能

2. CMake的使用

CMake支持大写、小写、混合大小写的命令。如果在编写CMakeLists.txt文件时使用的工具有对应的命令提示,那么大小写随缘即可,不要太过在意。

2.1 注释

2.1.1 注释行

CMake 使用 # 进行行注释,可以放在任何位置。

1
2
# 这是一个 CMakeLists.txt 文件
cmake_minimum_required(VERSION 3.0.0)

2.1.2 注释块

CMake 使用 #[[ ]] 形式进行块注释

1
2
3
4
#[[ 这是一个 CMakeLists.txt 文件。
这是一个 CMakeLists.txt 文件
这是一个 CMakeLists.txt 文件]]
cmake_minimum_required(VERSION 3.0.0)

2.1 只有源文件

2.1.1 共处一室

  1. 准备工作,为了方便测试,在我本地电脑准备了这么几个测试文件

    • add.c

      1
      2
      3
      4
      5
      6
      7
      
      #include <stdio.h>
      #include "head.h"
      
      int add(int a, int b)
      {
          return a+b;
      }
      
    • sub.c

      1
      2
      3
      4
      5
      6
      7
      8
      
      #include <stdio.h>
      #include "head.h"
      
      // 你好
      int subtract(int a, int b)
      {
          return a-b;
      }
      
    • mult.c

      1
      2
      3
      4
      5
      6
      7
      
      #include <stdio.h>
      #include "head.h"
      
      int multiply(int a, int b)
      {
          return a*b;
      }
      
    • div.c

      1
      2
      3
      4
      5
      6
      7
      
      #include <stdio.h>
      #include "head.h"
      
      double divide(int a, int b)
      {
          return (double)a/b;
      }
      
    • head.h

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      
      #ifndef _HEAD_H
      #define _HEAD_H
      // 加法
      int add(int a, int b);
      // 减法
      int subtract(int a, int b);
      // 乘法
      int multiply(int a, int b);
      // 除法
      double divide(int a, int b);
      #endif
      
    • main.c

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      
      #include <stdio.h>
      #include "head.h"
      
      int main()
      {
          int a = 20;
          int b = 12;
          printf("a = %d, b = %d\n", a, b);
          printf("a + b = %d\n", add(a, b));
          printf("a - b = %d\n", subtract(a, b));
          printf("a * b = %d\n", multiply(a, b));
          printf("a / b = %f\n", divide(a, b));
          return 0;
      }
      
  2. 上述文件的目录结构如下:

    1
    2
    3
    4
    5
    6
    7
    8
    
    $ tree
    .
    ├── add.c
    ├── div.c
    ├── head.h
    ├── main.c
    ├── mult.c
    └── sub.c
    
  3. 添加 CMakeLists.txt 文件

    在上述源文件所在目录下添加一个新文件 CMakeLists.txt,文件内容如下:

    1
    2
    3
    
    cmake_minimum_required(VERSION 3.0)
    project(CALC)
    add_executable(app add.c div.c main.c mult.c sub.c)
    

    接下来依次介绍一下在 CMakeLists.txt 文件中添加的三个命令:

    • cmake_minimum_required:指定使用的 cmake 的最低版本

      • 可选,非必须,如果不加可能会有警告
    • project:定义工程名称,并可指定工程的版本、工程描述、web主页地址、支持的语言(默认情况支持所有语言),如果不需要这些都是可以忽略的,只需要指定出工程名字即可。

      1
      2
      3
      4
      5
      6
      7
      
      # PROJECT 指令的语法是:
      project(<PROJECT-NAME> [<language-name>...])
      project(<PROJECT-NAME>
             [VERSION <major>[.<minor>[.<patch>[.<tweak>]]]]
             [DESCRIPTION <project-description-string>]
             [HOMEPAGE_URL <url-string>]
             [LANGUAGES <language-name>...])
      
    • add_executable:定义工程会生成一个可执行程序

      1
      
      add_executable(可执行程序名 源文件名称)
      
      • 这里的可执行程序名和project中的项目名没有任何关系

      • 源文件名可以是一个也可以是多个,如有多个可用空格或;间隔

        CMAKE
        1
        2
        3
        4
        
        # 样式1
        add_executable(app add.c div.c main.c mult.c sub.c)
        # 样式2
        add_executable(app add.c;div.c;main.c;mult.c;sub.c)
        
  4. 执行CMake 命令

    万事俱备只欠东风,将 CMakeLists.txt 文件编辑好之后,就可以执行 cmake命令了。

    1
    2
    
    # cmake 命令原型
    $ cmake CMakeLists.txt文件所在路径
    
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    
    $ tree
    .
    ├── add.c
    ├── CMakeLists.txt
    ├── div.c
    ├── head.h
    ├── main.c
    ├── mult.c
    └── sub.c
    
    0 directories, 7 files
    robin@OS:~/Linux/3Day/calc$ cmake .
    

    当执行cmake命令之后,CMakeLists.txt 中的命令就会被执行,所以一定要注意给cmake 命令指定路径的时候一定不能出错。

    执行命令之后,看一下源文件所在目录中是否多了一些文件:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
    $ tree -L 1
    .
    ├── add.c
    ├── CMakeCache.txt         # new add file
    ├── CMakeFiles             # new add dir
    ├── cmake_install.cmake    # new add file
    ├── CMakeLists.txt
    ├── div.c
    ├── head.h
    ├── main.c
    ├── Makefile               # new add file
    ├── mult.c
    └── sub.c
    

    我们可以看到在对应的目录下生成了一个makefile文件,此时再执行make命令,就可以对项目进行构建得到所需的可执行程序了。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    
    $ make
    Scanning dependencies of target app
    [ 16%] Building C object CMakeFiles/app.dir/add.c.o
    [ 33%] Building C object CMakeFiles/app.dir/div.c.o
    [ 50%] Building C object CMakeFiles/app.dir/main.c.o
    [ 66%] Building C object CMakeFiles/app.dir/mult.c.o
    [ 83%] Building C object CMakeFiles/app.dir/sub.c.o
    [100%] Linking C executable app
    [100%] Built target app
    
    # 查看可执行程序是否已经生成
    $ tree -L 1
    .
    ├── add.c
    ├── app					# 生成的可执行程序
    ├── CMakeCache.txt
    ├── CMakeFiles
    ├── cmake_install.cmake
    ├── CMakeLists.txt
    ├── div.c
    ├── head.h
    ├── main.c
    ├── Makefile
    ├── mult.c
    └── sub.c
    

    最终可执行程序app就被编译出来了(这个名字是在CMakeLists.txt中指定的)。

2.1.2 VIP 包房

通过上面的例子可以看出,如果在CMakeLists.txt文件所在目录执行了cmake命令之后就会生成一些目录和文件(包括 makefile 文件),如果再基于makefile文件执行make命令,程序在编译过程中还会生成一些中间文件和一个可执行文件,这样会导致整个项目目录看起来很混乱,不太容易管理和维护,此时我们就可以把生成的这些与项目源码无关的文件统一放到一个对应的目录里边,比如将这个目录命名为build:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

从入门到捕蛇者说

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值