0%

get新技能 - cmake基础使用

前言

最近准备从零创建一个工程库,于是就准备专门学习这一块的知识,最主要的就是编译系统搭建了。之前很少进行这方面的系统学习,都是基于已有的工程上面修改,一般就是加个文件或者选项,都是比较简单的,主要工作还是在代码逻辑的编写。鉴于是一个新的C语言的工程,那就选择cmake来作工程编译工具了。周末两天花了些时间,在掘金上面看了一个系列的博客,然后再对比的官网的使用文档学习一下cmake。

成功地跟着博客文章走了一轮下来,掌握了一些基本的使用,嗯,这就来稍微整理一下:

CMake的使用

setup

CMake最主要的就是CMakeLists.txt及相关的*.cmake的文件编写了。CMakeLists.txt是有层级的概念了, 可以通过include(dir)的方式把相关的CMakeLists.txt文件嵌套包含起来。这个方式跟shell脚本的引用类似。不过不同的CMakeLists.txt的工作目录在其所在的目录及build对应的目录下, 可以输出 CMAKE_CURRENT_SOURCE_DIR, CMAKE_CURRENT_BINARY_DIR变量查看。

第一步就是创建一个新目录,然后创建一个CMakeLists.txt文件。

根目录下的CMakeLists.txt必须填写工程名和cmake版本依赖, 还有可执行文件的创建:

1
2
3
4
5
6
7
8
9

cmake_minimum_required (VERSION 3.16)
project (hello
VERSION 0.0.2
DESCRIPTION "project hello to learn cmake usage."
LANGUAGES C)

add_executable(hello hello.c)

构建程序

创建一个hello.c的文件,里面简单输出个hello world。然后就是构建一个程序了。 构建的时候cmake自动生成一些文件,一般创建一个build目录,然后再在build目录下构建。

1
2
3
4
5
6
7
mkdir build
cd build
cmake ..
make

./hello

安装程序

构建之后创建的文件都在build目录下了,我们想要把hello文件拷贝到系统bin目录下,便于终端直接执行,需要用到install命令。在CMakeLists.txt下添加以下内容:

1
2
3
4
5
6
7
8
9
10
11
12

install (TARGETS hello DESTINATION bin) # 默认会安装到 /usr/local/bin中


# 重新执行命令

cmake ..
make
make install

# 然后就可以直接执行了
hello

特定函数检测

很多时候有些平台没有一些库,就不会提供部分函数功能。可以通过这个特性检测函数是否存在,设置到一个变量中,然后生成源程序文件中定义某个宏。我们在代码中根据这个宏来决定调用系统函数还是自定义函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

include (CheckFunctionExists)
check_function_exists (log HAVE_LOG) # 如果有log函数 则HAVE_LOG有值,否则没有值

configure_file (
"${PROJECT_SOURCE_DIR}/xxx.h.in"
"${PROJECT_BINARY_DIR}/xxx.h"
)

include_directories("${PROJECT_BINARY_DIR}")


# 在xxx.h.in 文件中添加内容
#cmakedefine HAVE_LOG // 如果HAVE_LOG有值 这个会自动生成 #define HAVE_LOG 否则 会生成注释/* undef HAVE_LOG */

文件生成

一种方式是使用configure_file命令, 根据input文件及当前的变量生成output文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# CMakeLists.txt包含如下内容

configure_file(
"config.h.in"
"config.h"
)

# config.h.in 内容为

#cmakedefine USE_MYMATH

#cmakedefine HAVE_LOG

#cmakedefine HAVE_MALLOC

#cmakedefine NOT_EXIST

#define V_MAJOR @VERSION_MAJOR@
#define V_MINOR @VERSION_MINOR@
#define V_PATCH @VERSION_PATCH@

另外一种方式就是使用add_custom_command来通过执行命令生成文件

1
2
3
4
5
6
7
8
9
# 创建自定义的版本信息, 可以使用shell脚本来达成目标
add_custom_command (
OUTPUT ${PROJECT_BINARY_DIR}/version.h
COMMAND ${PROJECT_SOURCE_DIR}/genversion.sh > ${PROJECT_BINARY_DIR}/version.h
)

# 需要指明依赖上述的OUTPUT,否则不会执行 COMMAND 的
add_executable(hello hello.c ${CMAKE_CURRENT_BINARY_DIR}/version.h)

安装包生成

通过使用cpack生成安装包

在CMakeLists.txt里面添加下面内容:

1
2
3
4
5
6
7
8
9
10

# build a CPack driven installer package
include (InstallRequiredSystemLibraries)
set (CPACK_RESOURCE_FILE_LICENSE
"${CMAKE_CURRENT_SOURCE_DIR}/License.txt")
set (CPACK_PACKAGE_VERSION_MAJOR "${Tutorial_VERSION_MAJOR}")
set (CPACK_PACKAGE_VERSION_MINOR "${Tutorial_VERSION_MINOR}")
include (CPack)


执行过cmake后, 可以直接运行 make package / package_source命令 生成压缩包。还有一个sh脚本用于执行安装。

还学习了一些cmake的语法,创建库等操作。

更多

通过一溜子的操作,掌握了最基本的使用。后面在实际的应用中再找官方文档看看, 应该足够满足应用了。

又get了一个新技能!

官网: https://cmake.org/

示例代码: https://gitee.com/fishmwei/blog_code/tree/master/cmake_learn


行动,才不会被动!

欢迎关注个人公众号 微信 -> 搜索 -> fishmwei,沟通交流。

博客地址: https://fishmwei.github.io/
掘金主页: https://juejin.cn/user/2084329776486919