一、CMake 简介
CMake 是一个跨平台的安装(编译)工具,可以用简单的语句来描述所有平台的安装(编译
过程)。他能够输出各种各样的 makefile 或者 project 文件。
Cmake 并不直接建构出最终的软件,而是产生标准的建构档(如 Unix 的 Makefile),然后
再以一般的建构方式使用。简单的说就是 CMake 基于 Makefile 做了二次开发。
二、安装 cmake
我当前的 CMake 版本:
有些项目有最低版本要求,如果版本过低,可能项目会编译不了,可以升级 CMake。
A> 卸载已经安装的旧版的 CMake[非必需]。
sudo apt-get autoremove cmake
B> 下载 CMake 压缩包:
wget https://cmake.org/files/v3.25/cmake-3.25.0-rc2-linux-x86_64.tar.gz
三、编译构建
通过 cmake 命令将 CMakeLists.txt 文件转化为 make 所需的 Makefile 文件
再用 make 命令编译源代码生成可执行程序或库文件
示例流程图如下:
1) 构建模式
CMake 支持两种构建模式,分别为 in-source build(源码中构建),out-of-source build
(源码外构建),下面分别来介绍一下这两种模式。
1.1 in-source build 模式
在源文件目录下构建,产生的二进制文件将与源文件生成在一个文件夹里。想要执行就
地构建,只需要在源码文件夹运行命令 cmake .,和之前说过的一样,CMake 只是生成了构
建工具需要的文件,具体的目标构建还需要构建工具来做,因此还需要运行 cmake --build
执行构建。
1.2 out-of-source build 模式
单独创建一个比如 build 文件夹,在该文件夹下构建二进制文件,与源代码文件分开。
执行源码外构建,需要运行如下命令。
mkdir build; cd ./build
cmake ..
cmake --build
一般使用源码外构建模式
2) 构建
基本构建语法:
cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=/path
cmake --build build -j4
cmake --install build/linux
注:
2.1 生成构建系统
cmake -S . -B build
# Configuration 阶段,为不同的构建工具生成相应文件。
cmake 读取 CMakeLists.txt 同时收集环境及项目配置信息,写入 CMakeCache.txt
中。此时在 build 目录下会生成 Makefile 文件。
-S 后接的位置是查找 CMakeLists 的位置,-S 选项可以整体缺省,默认会使用当前
目录
-B 后接的位置是生成的构建系统存放的位置,也就是 build 子目录(如果不存在,则
会自动创建)
-D 设置变量
2.2 执行构建
cmake --build build
使用构建工具构建默认 target,在 build 子目录下执行构建,生成目标 targets 文件
(如可执行文件、库等);或者可以进入 build 目录后,使用 cmake --build .,效果一样。
--build 指定编译生成的文件存放目录,其中就包括可执行文件
-j4 在编译时,我们可以添加选项让它进行多核编译加速
可以添加-v 或--verbose 显示编译细节
2.3 安装文件
cmake --install build/lib ## 安装路径 build/lib
cmake --install 是 CMake 工具的一个重要组成部分,它的主要功能是将构建的目标
(如可执行文件、库等)和其他相关文件(如头文件、配置文件等)安装到指定的位置。
这个过程是通过在 CMakeLists.txt 文件中使用 install 命令来实现的。
2.3.1 目标(Targets)
目标(Targets)是 CMake Install 的核心概念之一。在 CMake 中,目标主要指的是
我们需要构建的项目,比如一个可执行文件、一个库等。我们可以通过 add_executable
或 add_library 命令来创建一个目标,然后通过 target_link_libraries 命令来为目标添加依
赖。例如:CMakeLists.txt(2)文件中的:
2.3.2 安装路径(Install Paths)
安装路径(Install Paths)是指定目标安装的位置。在 CMake 中,我们可以通过
CMAKE_INSTALL_PREFIX 变 量 来 设 置 安 装 路 径 的 前 缀 , 然 后 在 install 命 令 中 通 过
DESTINATION 参数来指定目标的具体安装位置。
3) 构建目标
以面向对象的思路来编写 CMakeLists: 把生成的可执行文件,生成的静态动态库都统
一成构建目标(target),围绕着 target 使用形如 target_xxx 的命令添加源文件,添加依赖关系,
添加属性等等。
target 大致有以下的类型:
3.1> 可执行文件 target
使用源文件 test.cpp 编译得到可执行文件 test
add_executable(test)
target_sources(test PRIVATE test.cpp)
# or
add_executable(test PRIVATE test.cpp)
3.2> 静态库 target
使用源文件 static_fun.cpp 编译得到静态库 static_fun
add_library(static_fun STATIC)
target_sources(static_fun PRIVATE static_fun.cpp)
# ${PROJECT_SOURCE_DIR}/include 是编译时和使用时都需要使用的头文件搜索路
径
target_include_directories(static_fun PUBLIC ${PROJECT_SOURCE_DIR}/include)
3.3> 动态库 target
使用源文件 shared_fun.cpp 编译得到动态库 shared_fun
add_library(shared_fun SHARED)
target_sources(shared_fun PRIVATE shared_fun.cpp)
# ${PROJECT_SOURCE_DIR}/include 是编译时和使用时都需要使用的头文件搜索路
径
target_include_directories(shared_fun PUBLIC ${PROJECT_SOURCE_DIR}/include)
CMake 还允许一些特殊的库,比如由.o 文件组成的 OBJECT 库(主要为了节约编译时间),
或者仅仅由头文件组成的 INTERFACE 库(header-only)
add_library(demo SHARED)
add_library(Demo::demo ALIAS demo)
注:
add_library 可以缺省 STATIC|SHARED 参数,此时默认为 STATIC 全部生成静态库,但是
也可以通过指定 BUILD_SHARED_LIBS 为真,修改默认值为 SHARED 全部生成动态库
动态库目标会默认启动代码与位置无关的选项(POSITION_INDEPENDENT_CODE),相当于
GCC 的-fPIC 选项,对于静态库则不会自动启用
支持对目标起一个别名,这通常是为了增加命名空间前缀,在被链接时和导入的第三方依赖
的命名风格保持一致。
四、CMakeLists.txt 的语法
1) project 配置项目信息
例子:
project(CMakeTemplate VERSION 1.0.0 LANGUAGES C CXX)
CMakeTemplate 是项目的名称,0.1 是项目的版本号,LANGUAGES CXX 表明项目使用的语言
为 C++。对于 C/C++这个语句可以省略,因为默认语言就是 C 和 C++,注意如果只写 CXX 是
不支持 C 文件的,需要写明 LANGUAGES C CXX,对于 Fortran 等其它语言不可省略
2)set 设定编译
2.1> 指定编程语言版本
set(CMAKE_C_STANDARD 99)
set(CMAKE_CXX_STANDARD 11)
为了在不同机器上编译更加统一,最好指定语言的版本,比如声明 C 使用 c99 标准,C++
使用 c++11 标准;
2.2> 配置编译选项
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pipe -std=c99")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pipe -std=c++11")
通过命令 add_compile_options 命令可以为所有编译器配置编译选项(同时对多个编译
器生效); 通过设置变量 CMAKE_C_FLAGS 可以配置 c 编译器的编译选项; 而设置变量
CMAKE_CXX_FLAGS 可配置针对 c++编译器的编译选项。 比如:
add_compile_options(-Wall -Wextra -pedantic -Werror)
2.3> 配置编译类型
set(CMAKE_BUILD_TYPE Debug)
通过设置变量 CMAKE_BUILD_TYPE 来配置编译类型,可设置为:Debug、Release 等.
当然,更好的方式应该是在执行 cmake 命令的时候通过参数-D 指定:
cmake -B build -DCMAKE_BUILD_TYPE=Debug
2.3.1> 按照编译类型设置编译参数
Debug
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -g -O0")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g -O0")
Release