CMake 记录

make 和 makefile

gcc编译c程序文件,链接静态库和动态库,FFmpeg:https://ffmpeg.xianwaizhiyin.net/base-compile/linux-c-single.html

Make和Makefile快速入门:https://blog.csdn.net/Naisu_kun/article/details/116918571

cmakemakefile 的上层工具,它们的目的正是为了产生可移植的 makefile,并简化自己动手写 makefile 时的巨大工作量。

常用命令如下:

cmake
1
2
3
4
5
6
7
8
# cmake 最低版本需求
cmake_minimum_required(VERSION 3.13)
# 工程名称
project(cmake_study)
# 设置c++标准,这里是c++11
set(CMAKE_CXX_STANDARD 11)
# 编译源码生成目标
add_executable(cmake_study src/main.cc)

SET(set):定义变量

语法SET(VAR [VALUE] [CACHE TYPE DOCSTRING [FORCE]])

指令功能:用来显式的定义变量

例子SET (SRC_LST main.c other.c)

说明:用变量代替值,例子中定义 SRC_LST 代替后面的字符串。

我们可以使用 ${NAME} 来获取变量的名称。

cmake 常用变量

环境变量名 描述
CMAKE_BINARY_DIR, PROJECT_BINARY_DIR, <projectname>_BINARY_DIR 如果是 in source 编译,指得就是工程顶层目录,如果是 out-of-source 编译,指的是工程编译发生的目录。PROJECT_BINARY_DIR 跟其他指令稍有区别,现在,你可以理解为他们是一致的。
CMAKE_SOURCE_DIR, PROJECT_SOURCE_DIR, <projectname>_SOURCE_DIR 工程顶层目录。
CMAKE_CURRENT_SOURCE_DIR 当前处理的 CMakeLists.txt 所在的路径,比如上面我们提到的 src 子目录。
CMAKE_CURRRENT_BINARY_DIR 如果是 in-source 编译,它跟 CMAKE_CURRENT_SOURCE_DIR 一致,如果是 out-of-source 编译,他指的是 target 编译目录。
EXECUTABLE_OUTPUT_PATH , LIBRARY_OUTPUT_PATH 最终目标文件存放的路径。
PROJECT_NAME 通过 PROJECT 指令定义的项目名称。

cmake 系统信息

系统信息变量名 描述
CMAKE_MAJOR_VERSION CMAKE 主版本号,比如 2.4.6 中的 2
CMAKE_MINOR_VERSION CMAKE 次版本号,比如 2.4.6 中的 4
CMAKE_PATCH_VERSION CMAKE 补丁等级,比如 2.4.6 中的 6
CMAKE_SYSTEM 系统名称,比如 Linux-2.6.22
CMAKE_SYSTEM_NAME 不包含版本的系统名,比如 Linux
CMAKE_SYSTEM_VERSION 系统版本,比如 2.6.22
CMAKE_SYSTEM_PROCESSOR 处理器名称,比如 i686.
UNIX 在所有的类 UNIX 平台为 TRUE,包括 OS X 和 cygwin
WIN32 在所有的 win32 平台为 TRUE,包括 cygwin

cmake 编译选项

编译控制开关名 描述
BUILD_SHARED_LIBS 使用 ADD_LIBRARY 时生成动态库
BUILD_STATIC_LIBS 使用 ADD_LIBRARY 时生成静态库
CMAKE_C_FLAGS 设置 C 编译选项,也可以通过指令 ADD_DEFINITIONS()添加。
CMAKE_CXX_FLAGS 设置 C++编译选项,也可以通过指令 ADD_DEFINITIONS()添加。

不引入第三方库

目录结构:

markdown
1
2
3
4
5
6
7
8
9
./Demo1
|
+--- main.cc
|
+--- math/
|
+--- MathFunctions.cc
|
+--- MathFunctions.h

需要在项目根目录 Demo1 和 math 目录里各编写一个 CMakeLists.txt 文件。将 math 目录里的文件编译成静态库再由 main 函数调用。

math 目录中的 CMakeLists.txt:

cmake
1
2
3
4
5
6
# 查找当前目录下的所有源文件
# 并将名称保存到 DIR_LIB_SRCS 变量
aux_source_directory(. DIR_LIB_SRCS)

# 生成静态链接库MathFunctions
add_library (MathFunctions ${DIR_LIB_SRCS})

根目录中的 CMakeLists.txt :

cmake
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# CMake 最低版本号要求
cmake_minimum_required (VERSION 2.8)

# 项目名称信息,同时会自动生成 PROJECT_NAME 变量,使用 ${PROJECT_NAME} 即可访问到 Demo1
project (Demo1)

# 查找当前目录下的所有源文件
# 并将名称保存到 DIR_SRCS 变量,使用 ${DIR_SRCS} 可访问到
aux_source_directory(. DIR_SRCS)

# 添加 math 子目录
add_subdirectory(math)

# 指定生成目标
add_executable(Demo main.cc)

# 添加链接库
target_link_libraries(Demo MathFunctions)

单独命令:

cmake
1
2
3
4
5
# 将从第二个往后的参数保存到 DIR_SRCS 变量中,使用 ${DIR_SRCS} 可以访问到
set(DIR_SRCS
MathFunctions.cc
main.cc
)

引入第三方库

目录结构:

markdown
1
2
3
4
.
├── CMakeLists.txt
├── main.cpp
└── README.adoc

本地导入(find_package)

以 boost 为例,MakeLists.txt:

cmake
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
cmake_minimum_required(VERSION 3.5)

project (third_party_include)
# 使用库文件系统和系统查找 Boost,找到了,Boost_FOUND 为真,否则为假
find_package(Boost 1.46.1 REQUIRED COMPONENTS filesystem system)
# 1.46.1 代表需要库的最低版本;REQUIRED 表示找不到会报错;COMPONENTS 用于检测该库的对应组件是否存在,如果不存在则认为找到的库不满足条件。
if(Boost_FOUND)
message ("boost found")
else()
message (FATAL_ERROR "Cannot find Boost")
endif()

# 指定生成目标
add_executable(third_party_include main.cpp)

# 添加链接库
target_link_libraries(third_party_include PRIVATE Boost::filesystem)

这里使用 find_package 命令来在本地搜索对应的第三方库,Boost 代表需要查询的库名称;1.46.1 代表需要库的最低版本;REQUIRED 表示该库是必须的,如果找不到会报错;COMPONENTS 用于检测该库的对应组件是否存在,如果不存在则认为找到的库不满足条件。

外部导入(FetchContent)

以 GoogleTest 库为例:

cmake
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
cmake_minimum_required(VERSION 3.14)
project(my_project)

set(CMAKE_CXX_STANDARD 11)

# 引入 FetchContent 模块
include(FetchContent)
# 获取第三方库,可以是一个 URL 或者一个 Git 仓库
FetchContent_Declare(
googletest
URL https://github.com/google/googletest/archive/609281088cfefc76f9d0ce82e1ff6c30cc3591e5.zip
)

# 将这个第三方库引入项目
FetchContent_MakeAvailable(googletest)

使用外部头文件和库文件:

如果系统中安装,并提供了响应的.cmake文件,可以直接使用find_package()添加依赖:

bash
1
2
3
4
5
6
7
# 添加依赖项
find_package(OpenCV REQUIRED)
find_package(ZLIB REQUIRED)

# 添加源文件
add_executable(detect detect.cpp)
target_link_libraries(detect PRIVATE libdeploy.so ${OpenCV_LIBS} ${ZLIB_LIBRARIES})