关于CMAKE使用与开发

介绍CMAKE

CMAKE是一款跨平台的编译工具,区别与Linux的make系统,CMAKE的功能更丰富,可以将C/C++/java构建成相应的make文件以便于安装使用,同时一些好用的工具也都是使用Make进行安装的,效果不错推荐学习

从一个CPP说起

首先打开咱的开发环境,新建一个CPP文件,写一些比较基础的代码,用20级泰勒展开计算e的大小

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
26
27
28
29
30
31
32
33
34
35
36
#include <iostream>
using namespace std;
/*
* 利用泰勒展开计算自然常数e的大小
*/
//计算阶乘
long long int factorial(int number) {
long long int rtnNumber = 1;
for (int i = 1; i <= number;i++) {
rtnNumber *= i;
}
return rtnNumber;
}
//计算任意指数幂
long double power(int x,int level) {
long double m = 1;
for (int t = 0; t < level;t++) {
m *= x;
}
return m;
}
//表达出泰勒公式进行
long double getE(int x,int level) {
long double num = 1.0;
for (int j = 1; j <= level;j++) {
cout << (power(x, j)) / factorial(j) << endl;
num = num + (long double)(power(x, j)) / factorial(j);
}
return num;
}

int main(){
//输出结果,即getE(1,展开级数)
cout << getE(1,20) <<endl;
}

将CPP编译为makefile

内部构建

在编译为make文件之前先用g++编译输出一下

1
2
3
4
root@minloha:~/LearnCmake/demo01# g++ hello.cpp
root@minloha:~/LearnCmake/demo01# ./a.out
2.71828
root@minloha:~/LearnCmake/demo01#

可以看到输出是正常的,然后就可以去编写CMake的配置文件CMakeLists.txt

1
2
3
4
5
6
7
8
9
# 所有指令不区分大小写,变量区分大小写。为了便于区分,建议所有指令都大写
PROJECT (hello)
# 设置CMake变量SRC_LIST,并赋值为hello.cpp,多个文件一一列举就好
SET(SRC_LIST hello.cpp)
# 输出CMake编译自定义的输出信息
MESSAGE(STATUS "This is BINARY dir" ${HELLO_BINARY_DIR})
MESSAGE(STATUS "This is SOURCE dir" ${HELLO_SOURCE_DIR})
# 生成可执行文件hello
ADD_EXECUTABLE(hello ${SRC_LIST})

然后就可以使用CMake指令去生成文件cmake .指令末尾有一个点号,表示当前文件夹下的文件

1
2
3
4
5
6
7
8
9
root@minloha:~/LearnCmake/demo01# cmake .
-- This is BINARY dir
-- This is SOURCE dir
-- Configuring done
-- Generating done
-- Build files have been written to: /root/LearnCmake/demo01
root@minloha:~/LearnCmake/demo01# ls
a.out CMakeCache.txt CMakeFiles cmake_install.cmake CMakeLists.txt hello hello.cpp Makefile
root@minloha:~/LearnCmake/demo01#

然后就可以用make指令编译,bash进行执行

1
2
3
4
5
6
7
8
root@minloha:~/LearnCmake/demo01# make
Scanning dependencies of target hello
[ 50%] Building CXX object CMakeFiles/hello.dir/hello.cpp.o
[100%] Linking CXX executable hello
[100%] Built target hello
root@minloha:~/LearnCmake/demo01# ./hello
2.71828
root@minloha:~/LearnCmake/demo01#

外部构建

在cpp同级目录新建一个文件夹,把命令行cd进去,然后使用cmake ..进行生成

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
root@minloha:~/LearnCmake/demo02# mkdir build
root@minloha:~/LearnCmake/demo02# cd build/
root@minloha:~/LearnCmake/demo02/build# cmake ..
-- The C compiler identification is GNU 9.4.0
-- The CXX compiler identification is GNU 9.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
-- This is BINARY dir
-- This is SOURCE dir
-- Configuring done
-- Generating done
-- Build files have been written to: /root/LearnCmake/demo02/build
root@minloha:~/LearnCmake/demo02/build# ls
CMakeCache.txt CMakeFiles cmake_install.cmake Makefile
root@minloha:~/LearnCmake/demo02/build#

然后就可以打包发给你的小伙伴了

提高项目格局

为了让项目被别人看到后认为这是大佬,我们要专门新建一个文件夹(src)用于存放代码,同时注意,src文件夹下也要写一份CMakeLists.txt,目录结构是这样的

1
2
3
4
5
6
7
8
9
10
root@minloha:~/LearnCmake/demo03# tree
.
├── build
├── CMakeLists.txt
└── src
├── CMakeLists.txt
└── hello.cpp

2 directories, 3 files
root@minloha:~/LearnCmake/demo03#

在根目录下的CMakeLists.txt写如下面内容

1
2
3
4
# PROJECT(项目名)
PROJECT(YEAH)
# 添加源文件目录与生成make文件包含文件夹
ADD_SUBDIRECTORY(src bin)

在内层文件下src\CMakeLists.txt写入下面内容

1
2
# ADD_EXECUTABLE(可执行文件名 cpp代码)
ADD_EXECUTABLE(YEAH main.cpp)

然后我们移到build目录下面使用构建指令

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
26
27
28
29
30
31
root@minloha:~/LearnCmake/demo02/build# cmake ..
-- The C compiler identification is GNU 9.4.0
-- The CXX compiler identification is GNU 9.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
CMake Warning (dev) in CMakeLists.txt:
No cmake_minimum_required command is present. A line of code such as

cmake_minimum_required(VERSION 3.16)

should be added at the top of the file. The version specified may be lower
if you wish to support older CMake versions for this project. For more
information run "cmake --help-policy CMP0000".
This warning is for project developers. Use -Wno-dev to suppress it.

-- Configuring done
-- Generating done
-- Build files have been written to: /root/LearnCmake/demo02/build
root@minloha:~/LearnCmake/demo02/build# ls
bin CMakeCache.txt CMakeFiles cmake_install.cmake Makefile
root@minloha:~/LearnCmake/demo02/build#

注意出现报错,这是因为在src目录下的CMakeLists.txt文件,我们只写入了一行,而这并不被新版本的CMake认同,不过不影响编译输出。然后我们就make一下就可以找到生成的文件夹bin

1
2
3
4
5
6
7
8
9
10
11
root@minloha:~/LearnCmake/demo02/build# make
Scanning dependencies of target YEAH
[ 50%] Building CXX object bin/CMakeFiles/YEAH.dir/main.o
[100%] Linking CXX executable YEAH
[100%] Built target YEAH
root@minloha:~/LearnCmake/demo02/build# ls
bin CMakeCache.txt CMakeFiles cmake_install.cmake Makefile
root@minloha:~/LearnCmake/demo02/build# cd bin/
root@minloha:~/LearnCmake/demo02/build/bin# ls
CMakeFiles cmake_install.cmake Makefile YEAH
root@minloha:~/LearnCmake/demo02/build/bin#

把项目刻进硬盘里

这一步就是要讲CMake生成可以进行make install指令的文件,在这之前先开辟新的文件结构,按照下表所示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
root@minloha:~/LearnCmake/demo03# tree
.
├── build
├── CMakeLists.txt
├── COPYRIGHT
├── doc
│   └── YEAH.txt
├── runYEAH.sh
└── src
├── CMakeLists.txt
└── main.cpp

3 directories, 6 files
root@minloha:~/LearnCmake/demo03#

把根下的CMakeLists.txt内容修改为这样

1
2
3
4
5
6
7
8
9
10
11
12
13
PROJECT(YEAH)
ADD_SUBDIRECTORY(src bin)
# 同上
# ---------------
# 安装绝对文件要指定安装路径,share/doc/cmake为安装路径,可以使用绝对路径
# 如果是相对路径则默认是新建变量:CMAKE_INSTALL_PREFIX,按照其内部存储进行安装,默认值/usr/local
INSTALL(FILES COPYRIGHT DESTINATION share/doc/cmake)

# 安装指定运行脚本,在这里是runYEAH.sh,文件安装到/usr/local/bin目录
INSTALL(PROGRAMS runYEAH.sh DESTINATION bin)

# 指定文件的安装目录,也就是根文件的doc目录安装到share/doc/cmake,切记doc可以把文件夹一起安装,而doc/只会把内部的文件安装
INSTALL(DIRECTORY doc/ DESTINATION share/doc/cmake)

其他文件的具体内容可以自行修改了,比如runYEAH.sh或者COPYRIGHT,YEAH.txt,总之不是CAMakeLists.txt都可以动,然后就切换到build目录下进行cmake

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
26
27
28
root@minloha:~/LearnCmake/demo03/build# cmake ..
-- The C compiler identification is GNU 9.4.0
-- The CXX compiler identification is GNU 9.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
CMake Warning (dev) in CMakeLists.txt:
No cmake_minimum_required command is present. A line of code such as

cmake_minimum_required(VERSION 3.16)

should be added at the top of the file. The version specified may be lower
if you wish to support older CMake versions for this project. For more
information run "cmake --help-policy CMP0000".
This warning is for project developers. Use -Wno-dev to suppress it.

-- Configuring done
-- Generating done
-- Build files have been written to: /root/LearnCmake/demo03/build

然后就可以make构建然后make安装了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
root@minloha:~/LearnCmake/demo03/build# make
Scanning dependencies of target YEAH
[ 50%] Building CXX object bin/CMakeFiles/YEAH.dir/main.o
[100%] Linking CXX executable YEAH
[100%] Built target YEAH
lroot@minloha:~/LearnCmake/demo03/build# ls
bin CMakeCache.txt CMakeFiles cmake_install.cmake Makefile
root@minloha:~/LearnCmake/demo03/build# cd bin
root@minloha:~/LearnCmake/demo03/build/bin# ls
CMakeFiles cmake_install.cmake Makefile YEAH
root@minloha:~/LearnCmake/demo03/build/bin# make install
[100%] Built target YEAH
Install the project...
-- Install configuration: ""
root@minloha:~/LearnCmake/demo03/build/bin#

共享库的构建

将上一次的make文件复制一份继续写,项目结构是这样的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
root@minloha:~/LearnCmake/demo04# tree
.
├── build
├── CMakeLists.txt
├── COPYRIGHT
├── doc
│   └── YEAH.txt
├── lib
│   ├── CMakeLists.txt
│   ├── main.cpp
│   └── main.h
└── runYEAH.sh

3 directories, 7 files
root@minloha:~/LearnCmake/demo04#

所谓动态库就是windows中常见的.dll动态链接库,静态库就是.lib文件,首先我们先要有一个.h头文件

1
2
3
4
5
6
7
8
#include <iostream>
using namespace std;
#ifndef _MAIN_H_
#define _MAIN_H_
long long int factorial(int number);
long double power(int x,int level);
long double getE(int x,int level);
#endif

讲头文件包含进cpp文件内,也就是使用下面的语句

1
#include "main.h"

在lib下的CMakeLists.txt写入下面内容

1
2
3
4
# 定义一个LIBYEAH_SRC变量,保存数据是main.cpp
SET(LIBYEAH_SRC main.cpp)
# SHARED是生成共享库,STATIC是生成静态库
ADD_LIBRARY(YEAH SHARED ${LIBYEAH_SRC})

然后就可以生成试试了

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
26
27
28
29
30
31
32
33
34
35
36
37
root@minloha:~/LearnCmake/demo04/build# cmake ..
-- The C compiler identification is GNU 9.4.0
-- The CXX compiler identification is GNU 9.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
CMake Warning (dev) in CMakeLists.txt:
No cmake_minimum_required command is present. A line of code such as

cmake_minimum_required(VERSION 3.16)

should be added at the top of the file. The version specified may be lower
if you wish to support older CMake versions for this project. For more
information run "cmake --help-policy CMP0000".
This warning is for project developers. Use -Wno-dev to suppress it.

-- Configuring done
-- Generating done
-- Build files have been written to: /root/LearnCmake/demo04/build
root@minloha:~/LearnCmake/demo04/build# make
Scanning dependencies of target YEAH
[ 50%] Building CXX object bin/CMakeFiles/YEAH.dir/main.o
[100%] Linking CXX shared library libYEAH.so
[100%] Built target YEAH
root@minloha:~/LearnCmake/demo04/build# cd bin/
root@minloha:~/LearnCmake/demo04/build/bin# ls
CMakeFiles cmake_install.cmake libYEAH.so Makefile
root@minloha:~/LearnCmake/demo04/build/bin#

可以看到生成了linYEAH.so的动态库

指令总结与补充

指令功能
PROJECT (项目名)定义项目
SET(变量名 值)定义一个Make变量保存数据
MESSAGE(STATUS 字符串)使用make时输出一些信息或警告
ADD_EXECUTABLE(生成文件名 源文件)添加CMAKE时生成的可执行文件
ADD_SUBDIRECTORY( 当前目录 生成的目录)将已有的目录作为Make生成的子目录
INSTALL(类型 文件 DESTINATION 目标文件夹)将不同类型的文件生成到不同的文件夹中,类型可以参考上文
ADD_LIBRARY(库名 静态/动态 源文件)将源文件生成为动态或静态库

全篇的运行Cmake都有警告,解决办法是在CMakeLists.txt中加入cmake_minimum_required( VERSION 2.8 ),降低Cmake语言版本即可


关于CMAKE使用与开发
https://blog.minloha.cn/posts/172606d13a374e2022012649.html
作者
Minloha
发布于
2022年1月26日
更新于
2024年9月15日
许可协议