CMake基础篇(三)——变量

前言:
   本篇文章帮助你快速熟悉CMake变量的使用。

1 介绍

  Cmake定义变量有显示和隐式两种。显示为使用 set 函数定义的变量,隐式是CMake自动创建的变量。CMake新增变量不需要提前有个变量定义操作,直接使用即自动完成变量定义。
  更详细的变量信息查询可以访问 官网对CMake变量的说明

2 隐式变量

  比如以下代码, project(ProjectName) 函数定义了该项目的名称为 ProjectName ,同时CMake会隐式的定义 ProjectName_SOURCE_DIRProjectName_BINARY_DIR 两个变量。

1
2
3
project(ProjectName)
message(STATUS "${ProjectName_SOURCE_DIR}")
message(STATUS "${ProjectName_BINARY_DIR}")

3 显式变量

  使用函数 set 显式的定义变量,如下。 name 为变量名, value 为变量值。

1
2
3
project(ProjectName)
set(name "value")
message(STATUS "${name}")

  输出值为。

1
2
╰─ cmake ..
-- value

4 多个值

  CMake的变量可以同时有多个值。

1
2
3
project(ProjectName)
set(name "value1" "value2" "value3")
message(STATUS "${name}")

  输出为。

1
2
╰─ cmake ..
-- value1;value2;value3

5 引用变量

  在CMake中引用变量的方式为 ${VariableName}$ENV{VariableName} ,也可以引用系统的环境变量。
  引用CMake变量示例如下。

1
2
3
project(ProjectName)
set(name "value")
message(STATUS "${name}")

  引用系统环境变量示例如下。

1
2
project(ProjectName)
message(STATUS "$ENV{SHELL}")

  CMake的变量可以都多个值,也即列表。CMake中可以按照索引读取列表元素的值,但修改某个列表元素的值则相对麻烦,需要先按索引移除某个元素,然后按索引插入一个元素值。当列表比较大或修改元素值比较频繁时,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
project(ProjectName)

# function(FunName Param0 Param1 RtnVal)
# math(EXPR Sum "${Param0} + ${Param1}")
# set(${RtnVal} ${Sum} PARENT_SCOPE)
# endfunction()
#
# FunName(1 2 Var)
# message(STATUS "${Var}")

set(Var 0 1 2)

list(GET Var 0 Var0) # Read value. Idex is 0.
list(GET Var 1 Var1)

message(STATUS "Var: ${Var}")
message(STATUS "Var0: ${Var0}")
message(STATUS "Var1: ${Var1}")

list(REMOVE_AT Var 0)

message(STATUS "Var: ${Var}")

list(INSERT Var 0 3)

message(STATUS "Var: ${Var}")

  输出结果为。

1
2
3
4
5
6
╰─ cmake ..
-- Var: 0;1;2
-- Var0: 0
-- Var1: 1
-- Var: 1;2
-- Var: 3;1;2

6 CMake自带变量

6.1 PROJECT_NAME

   project() 设置的项目名称。

1
2
project(ProjectName)
message(STATUS "${PROJECT_NAME}")

  输出为。

1
2
╰─ cmake ..
-- ProjectName

6.3 CMAKE_PROJECT_NAME

  CMakeLists.txt允许嵌套调用, CMAKE_PROJECT_NAME 为最顶级CMakeLists.txt中最近一次 project() 函数定义的项目名。
  以下是示例,假设目录结构为。

1
2
3
4
5
6
7
8
9
10
11
╰─ tree
.
├── build
│ └── Makefile
├── CMakeLists.txt
├── main.c
├── README.md
└── src
├── CMakeLists.txt
└── sub
└── CMakeLists.txt

  以下是三个CMakeLists.txt文件内容。
  ./CMakeLists.txt。

1
2
3
4
5
project(ProjectName)
project(ProjectName1)
project(ProjectName2)
add_subdirectory(src)
message(STATUS "${CMAKE_PROJECT_NAME}")

  ./src/CMakeLists.txt内容如下。

1
2
3
project(Project_src)
add_subdirectory(sub)
message(STATUS "${CMAKE_PROJECT_NAME}")

  ./src/sub/CMakeLists.txt内容如下。

1
2
project(Project_sub)
message(STATUS "${CMAKE_PROJECT_NAME}")

6.3 CMAKE_BINARY_DIR

  为CMake顶层构建时的二进制生成路径。

1
2
project(ProjectName)
message(STATUS "${CMAKE_BINARY_DIR}")

  输出如下。

1
2
╰─ cmake ..
-- /home/calm/calm/github/litchi/build

6.4 PROJECT_BINARY_DIR / _BINARY_DIR / CMAKE_CURRENT_BINARY_DIR

  CMake是允许嵌套多个子项目的,这个变量是当前CMake项目的二进制生成路径。
  目录结构如下。

1
2
3
4
5
6
7
8
9
╰─ tree
.
├── build
│ └── Makefile
├── CMakeLists.txt
├── main.c
├── README.md
└── src
└── CMakeLists.txt

  ./CMakeLists.txt。

1
2
3
project(ProjectName)
add_subdirectory(src)
message(STATUS "${CMAKE_BINARY_DIR}")

  ./src/CMakeLists.txt。

1
2
project(Project_src)
message(STATUS "${PROJECT_BINARY_DIR}")

  输出如下。

1
2
3
╰─ cmake ..
-- /home/calm/calm/github/litchi/build/src
-- /home/calm/calm/github/litchi/build

6.5 CMAKE_SOURCE_DIR

  为最顶层CMakeLists.txt的路径,所以通常是工程根目录。

1
2
3
project(ProjectName)
add_subdirectory(src)
message(STATUS "${CMAKE_SOURCE_DIR}")

6.6 PROJECT_SOURCE_DIR / _SOURCE_DIR / CMAKE_CURRENT_SOURCE_DIR

  当前项目的CMakeLists.txt文件所在的目录。目录结构如下。

1
2
3
4
5
6
7
8
9
╰─ tree
.
├── build
│ └── Makefile
├── CMakeLists.txt
├── main.c
├── README.md
└── src
└── CMakeLists.txt

  ./CMakeLists.txt。

1
2
3
project(ProjectName)
add_subdirectory(src)
message(STATUS "${PROJECT_SOURCE_DIR}")

  ./src/CMakeLists.txt。

1
2
project(Project_src)
message(STATUS "${PROJECT_SOURCE_DIR}")

  输出结果如下。

1
2
3
╰─ cmake ..
-- /home/calm/calm/github/litchi/src
-- /home/calm/calm/github/litchi

6.7 CMAKE_VERSION/CMAKE_MAJOR_VERSION/CMAKE_MINOR_VERSION/CMAKE_PATCH_VERSION

  为CMake的版本号,版本号的构成有三部分 .. 构成,这三部分分别可以用一个变量获取。
  代码如下。

1
2
3
4
5
project(ProjectName)
message(STATUS "${CMAKE_VERSION}")
message(STATUS "${CMAKE_MAJOR_VERSION}")
message(STATUS "${CMAKE_MINOR_VERSION}")
message(STATUS "${CMAKE_PATCH_VERSION}")

  输出结果为。

1
2
3
4
5
╰─ cmake ..
-- 3.22.1
-- 3
-- 22
-- 1

6.8 VERSION_LESS/VERSION_GREATER/VERSION_EQUAL/VERSION_LESS_EQUAL/VERSION_GREATER_EQUAL

  这几个变量结合 if 语句可以实现对版本号的检查。