CMake基础入门-1

简介: CMake基础入门

CMake是一个跨平台的安装(编译)工具,可以用简单的语句来描述所有平台的安装(编译过程),能够输出各种各样的makefile或者project文件。可以理解为,编写Makefile难度太大,CMake基于Makefile做了二次开发。


安装CMake

我使用的是Ubuntu 22.04.2,在终端输入

sudo apt install cmake

完成之后,检查版本号,看是否安装成功

cmake -version

结果是

zxm@ubuntu:~$ cmake -version
cmake version 3.22.1



一、一个目录下有一个源文件(入门)


1.1 预定义的变量


  • CMAKE_CURRENT_LIST_DIR:CMakeLists 所在的路径
  • CMAKE_BINARY_DIR 、PROJECT_BINARY_DIR、<projectname>_BINARY_DIR: 工程编译发生的目录。表示当前的构建目录,即执行 CMake 构建命令时所在的目录的路径。
  • CMAKE_SOURCE_DIR、PROJECT_SOURCE_DIR、<projectname>_BINARY_DIR: 工程顶层目录。表示包含项目名的最近一个 CMakeLists.txt 文件所在的目录的路径。
  • CMAKE_CURRENT_SOURCE_DIR:表示当前正在处理的 CMakeLists.txt 文件的所在目录的绝对路径。
  • CMAKE_C_COMPILER:指定 C 编译器
  • CMAKE_CXX_COMPILER:指定 C++ 编译器
  • EXECUTABLE_OUTPUT_PATH:可执行文件输出的存放路径
  • LIBRARY_OUTPUT_PATH:库文件输出的存放路径
  • CMAKE_BUILD_TYPE: 构建的类型,例如 Debug(默认有-g) ,Release


1.2 语法介绍

cmake_minimum_required

用于指定 cmake 的最小版本要求。

cmake_minimum_required (VERSION 2.8)

project

通常作为 CMakeLists.txt 文件的第一条指令出现,用于定义项目的基本信息。通过设置属性,可以提供项目的名称、版本号、描述等信息,并指定项目所用的编程语言。

project(<project_name>
        [VERSION <major>[.<minor>[.<patch>[.<tweak>]]]]
        [DESCRIPTION <project_description>]
        [HOMEPAGE_URL <homepage_url>]
        [LANGUAGES <language>...])

其中,<project_name> 是项目的名称,是 project 指令的必填参数。

<major>, <minor>,<patch>,<tweak> 可选地指定项目的版本号。


除了名称和版本号外,project 指令还支持设置其他可选属性:

-DESCRIPTION:可选地设置项目的描述信息。

HOMEPAGE_URL:可选地设置项目的主页 URL。

LANGUAGES:可选地指定项目使用的编程语言。默认情况表示支持所有语言。


set

用于创建新的变量,修改已存在的变量的值,以及删除变量。

set(<variable_name> <value> CACHE <type> <docstring> [FORCE])

其中:


  • <variable_name> 是要设置的变量名。
  • <value> 是要设置的变量的值。
  • CACHE 是一个可选的关键字,用于将变量设置为缓存变量,允许用户通过命令行或图形界面进行配置。
  • <type> 是变量的类型,可以是 STRING、BOOL、PATH 等。
  • <docstring> 是关于这个变量的描述文本,可选。
  • FORCE 是一个可选的关键字,用于强制覆盖之前定义的同名变量的值。

举个例子


// 设置了一个名为 SRC_FILES 的变量,其值为一组源文件的路径。
set(SRC_FILES src/main.cpp src/foo.cpp)
// 设置了一个名为 ENABLE_DEBUG 的缓存变量,其值为布尔类型,用于控制是否启用调试模式。
set(ENABLE_DEBUG TRUE CACHE BOOL "Enable debug mode")
// 设置了一个名为 MY_PATH 的缓存变量,其值为路径类型,指定了某个目录的路径。
set(MY_PATH "/path/to/something" CACHE PATH "Path to something")

message

用于在配置过程中打印一些特定信息,方便调试和打印状态。


message([<mode>] "message to display" ...)

其中,<mode> 是一个可选参数,用于指定消息的模式。常见的模式有以下几种:


  • STATUS:将消息以普通状态打印出来。
  • WARNING:将消息以警告的方式打印出来。
  • AUTHOR_WARNING:将消息以作者警告的方式打印出来。
  • SEND_ERROR:将消息以错误的方式打印出来,并停止配置过程。
  • FATAL_ERROR:将消息以致命错误的方式打印出来,并终止配置和构建过程。


add_executable

创建可执行文件目标,用于将一组源文件编译为可执行文件。


add_executable(<target_name> [WIN32] [MACOSX_BUNDLE]
               [EXCLUDE_FROM_ALL]
               source1 [source2 ...])

其中


  • <target_name> 是要创建的可执行文件的名称,可以自定义。
  • [WIN32] 和 [MACOSX_BUNDLE] 是可选的标志,用于指定平台特定的属性。
  • [EXCLUDE_FROM_ALL] 也是可选的标志,用于将目标从默认构建中排除。

举个例子

// 创建了一个名为 MyExecutable 的可执行文件目标,
// 并指定了三个源文件 main.cpp、foo.cpp 和 bar.cpp。
add_executable(MyExecutable main.cpp foo.cpp bar.cpp)

1.3 最基础的实例

1)创建两个文件main.c和CMakeLists.txt

main.c里面编写


#include <stdio.h>
int main(){
    printf("This is CMake;\n");
    return 0;
}

CMakeLists.txt里面编写


# 单个目录的实现
# CMake最低版本号的要求
cmake_minimum_required(VERSION 2.8)
# 工程项目的名称,注意不是执行文件名
project(Zxm)
# 手动加入文件 ${变量名},比如${SRC_LIST}
set(SRC_LIST main.c)
# message 和 echo 类型
message(STATUS "PROJECT_BINARY_DIR DIR " ${PROJECT_BINARY_DIR})
message(STATUS "PROJECT_SOURCE_DIR DIR " ${PROJECT_SOURCE_DIR})
# 创建可执行文件,名为hello
add_executable(hello ${SRC_LIST})  

2)在终端输入cmake .,.表示当前目录

59e6901b0e294994b9250a662261b91a_404f000703874f8e89c2ac066e277f0b.png

生成了下面几个文件

1026d9c120b838568468b7988e91a960_5c53eba1c25646c7aab88c0d349b8f3b.png


3)在终端输入make,生成可执行文件hello


3b30adaad8201d8d769ce865d8249193_a8ad6d53e24c47df8fd9c20eab682632.png67a59749c766a7fcbbaffd0b18b0101a_b5ef499ecf8441dba4a80f4cb1d48a90.png


3)执行./hello


e3d9303641f765978b616c0a6b211c21_2d6e83219b9242c187d4732105fd5067.png

4)如果还有一个main2.c,那么修改CMakeLists.txt,其他的一样


#单个目录的实现
# CMake最低版本号的要求
cmake_minimum_required(VERSION 2.8)
# 工程项目的名称,注意不是执行文件名
project(Zxm)
# 手动加入文件 ${变量名},比如${SRC_LIST}
set(SRC_LIST main.c)
set(SRC_LIST2 main2.c)
# message 和 echo 类型
message(STATUS "PROJECT_BINARY_DIR DIR " ${PROJECT_BINARY_DIR})
message(STATUS "PROJECT_SOURCE_DIR DIR " ${PROJECT_SOURCE_DIR})
# 创建可执行文件,名为hello
add_executable(hello ${SRC_LIST})  
add_executable(hello2 ${SRC_LIST}) 

1.4 第一步优化:build目录

把很多生成的文件和源码混在一起,是一个很容易挨打的行为。我们可以单独创建一个子目录build,用来存放cmke后的结果。


实操流程

1)创建子目录build,进入到build

cd build/

2)终端输入cmake ..

# ..表示二级目录
cmake ..

3)终端输入make


这样就显得干净多了

5d329f8abc09ea06b8f9d69012705b4c_7ac33ed7a0d44c6c8d7bc7573ad45f43.png


1.5 第二步优化:src目录

为工程添加一个子目录src,用来放置工程源代码。结构如图


448139f18e104b7a8a11783c76be0450_0d00cb6f8bf24c05a714b487d48d4b78.png

1.5.1 实操流程

1)创建子目录src,把main.c移到该目录下。并为任何子目录建立一个 CMakeLists.txt(跟工程1的一致)


#单个目录的实现
# CMake最低版本号的要求
cmake_minimum_required(VERSION 2.8)
# 工程项目的名称,注意不是执行文件名
project(Zxm)
# 手动加入文件 ${变量名},比如${SRC_LIST}
set(SRC_LIST main.c)
# message 和 echo 类型
message(STATUS "PROJECT_BINARY_DIR DIR " ${PROJECT_BINARY_DIR})
message(STATUS "PROJECT_SOURCE_DIR DIR " ${PROJECT_SOURCE_DIR})
message(STATUS "CMAKE_CURRENT_SOURCE_DIR " ${CMAKE_CURRENT_SOURCE_DIR})
# 创建可执行文件,名为hello
add_executable(hello ${SRC_LIST})  

2)在主目录下,建立一个 CMakeLists.txt。主要点是add_subdirectory(src bin)


#单个目录的实现
# CMake最低版本号的要求
cmake_minimum_required(VERSION 2.8)
# 工程项目的名称,注意不是执行文件名
project(Zxm)
# 手动加入文件 ${变量名},比如${SRC_LIST}
set(SRC_LIST main.c)
# message 和 echo 类型
message(STATUS "PROJECT_BINARY_DIR DIR " ${PROJECT_BINARY_DIR})
message(STATUS "PROJECT_SOURCE_DIR DIR " ${PROJECT_SOURCE_DIR})
# CMAKE_CURRENT_SOURCE_DIR它的CMakeLists.txt所在的当前源目
MESSAGE(STATUS "CMAKE_CURRENT_SOURCE_DIR " ${CMAKE_CURRENT_SOURCE_DIR})
# 添加子目录src,并将生成的二进制文件存放到 bin 目录中
add_subdirectory(src bin)

3)进入build目录,执行cmake .. 和 make


cd build
cmake ..
make

5b666bbc32d3df07f7af449634c3c6e1_4fee576eb6dc433daf4cdfebe8be4d75.png


注意到生成的可执行文件是存放到 bin 目录中,因此需要在bin目录下执行


cd bin
./hello

e754b4e5052a679896a1f19ea8fff364_1ace18c17061429bbb48e32af32bd3c9.png


1.5.2 add_subdirectory

用于向 CMake 构建系统添加一个子目录。这个子目录可以包含另一个独立的 CMakeLists.txt 文件,用于管理子目录下的源码、库文件或其他构建内容。

add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL])

其中:


  • source_dir:要添加为子目录的源码目录,需要包含一个独立的 CMakeLists.txt 文件。
  • binary_dir:可选参数,指定生成的二进制文件(如可执行文件、库文件)所存放的目录。如果不提供该参数,则默认为在当前构建目录生成二进制文件。
  • EXCLUDE_FROM_ALL:可选参数,表示将该子目录排除在默认构建(make 或 build)之外。

举个例子,假设我们的项目包含两个子目录,分别是 src 和 tests:


project/
├── CMakeLists.txt
├── src/
│   ├── CMakeLists.txt
│   └── ...
└── tests/
    ├── CMakeLists.txt
    └── ...

在主项目的 CMakeLists.txt 文件中,我们可以使用 add_subdirectory命令将这两个子目录添加进来:


add_subdirectory(src )
add_subdirectory(tests)

这样,在构建过程中,CMake 会先依次进入 src 目录和 tests 目录,执行这两个子目录下的 CMakeLists.txt 文件,分别进行对应的构建操作。

目录
相关文章
|
4月前
|
Dart IDE Unix
CMake 教程3
CMake 教程
40 1
|
4月前
|
缓存 Unix 程序员
CMake 教程1
CMake 教程
70 1
|
4月前
CMake 教程2
CMake 教程
27 0
|
6月前
|
C++ 缓存 Unix
面向 C++ 的现代 CMake 教程(四)(4)
面向 C++ 的现代 CMake 教程(四)
53 0
|
6月前
|
C++ 开发者 缓存
面向 C++ 的现代 CMake 教程(四)(1)
面向 C++ 的现代 CMake 教程(四)
66 0
|
6月前
|
C++ 开发者 Unix
面向 C++ 的现代 CMake 教程(四)(5)
面向 C++ 的现代 CMake 教程(四)
61 0
|
6月前
|
C++ 存储 测试技术
面向 C++ 的现代 CMake 教程(五)(2)
面向 C++ 的现代 CMake 教程(五)
72 0
|
6月前
|
C++ 缓存 存储
面向 C++ 的现代 CMake 教程(一)(3)
面向 C++ 的现代 CMake 教程(一)
141 0
|
6月前
|
存储 算法 C++
面向 C++ 的现代 CMake 教程(五)(5)
面向 C++ 的现代 CMake 教程(五)
49 0
|
6月前
|
C++ 开发者 开发工具
面向 C++ 的现代 CMake 教程(四)(2)
面向 C++ 的现代 CMake 教程(四)
69 0