2. CMake 语法的基本指令

2. CMake 语法的基本指令

主要介绍 CMake 脚本语言的一些基础语法怎么使用, 这个行为就像学习 C/C++编程语言一样, 从变量, 字符串, 列表这些基础的数据类型, 然后一步步延伸到 if/else, for 等这类的基本逻辑函数,了解 CMake 脚本的基本语法.

CMake 官网对指令的划分

我希望带大家一起了解的内容如下图所示,从这些基本的指令使用方法开始,了解 CMake 这个工具,也为了方便进行 CMake 的其他知识学习!

2. CMake 语法的基本指令_第1张图片

2.1 最小 CMakeLists.txt 文件包含的内容

  1. 举个例子之前的最小的 CMake 工程就只包括两个内容main.c和它的头文件hex.h, 以及一个math.h的动态库libm.so, 整个的文件结构如下所示:
.
├── hex.h
└── main.c
  1. 此时的最小构建的 CMakeLists.txt 文件就包括这些内容:
cmake_minimum_required(VERSION 3.0)
project(TEST)

add_executable(test main.c hex.h)
target_link_libraries(test m)
  1. 依次解读这几个指令:
  • cmake_minimum_required(最小版本号): 指定了 CMake 的最低版本要求;

  • project(项目名): 定义了项目的名称;

  • add_executable(可执行程序名 源文件名称): 这行命令用于添加一个可执行文件的构建目标; add_executable(test main.c hex.h)在这个例子中, 它会编译名为"test"的可执行文件, 并将 main.chex.h 作为源代码文件, CMake 会自动根据这些源文件来生成构建规则;

  • target_link_libraries(可执行程序名 动态库名称): 这行命令用于指定构建目标的链接库; target_link_libraries(test m)表示"test"可执行文件需要链接动态数学库m(libm.so);

动态库的名称均是形如libxxx.solib开头, .so结尾, 其中的xxx便是动态库的名称了.

  1. CMakeLists.txt每一行的顺序排列是有一定规则的:cmake_minimum_required 通常是在 CMakeLists.txt 文件的开头, 用于指定 CMake 最低版本要求, 这样做可以确保构建系统在运行时具有所需的 CMake 版本; project 命令通常紧跟在 cmake_minimum_required 之后, 用于定义项目的名称和相关属性, 这样做可以在后续的构建规则中使用项目的属性; add_executable 命令用于添加构建目标, 并定义源代码文件, 它通常紧跟在 project 命令之后, 以便在项目中创建可执行文; target_link_libraries 命令用于指定链接库, 它位于构建目标指令add_executable之后, 以确保在构建可执行文件之前已经定义了所需的链接库.

2.2 CMake 的预定义宏和输出命令

为了方便了解 CMakeLists.txt 中,一些变量的结果,因此我们先提前介绍一下 CMake 中的宏和它的输出指令的用法

2.2.1 CMake 的输出 message 指令

  1. message指令:用于在构建过程中输出自定义的消息或变量的值, 语法如下:message([] "message_text" ...),其中,mode 是可选参数,指定消息的类型, message_text是要输出的消息文本,可以包含变量、表达式和字符串.(在 CMake 指南中 []间的内容都是可选内容)

  2. 常用的 mode 有以下几种:

  • STATUS:将消息输出为构建过程中的状态信息,通常用于显示一些进度或提示信息.
  • WARNING:将消息输出为警告信息,通常用于显示一些警告或注意事项.
  • AUTHOR_WARNING:将消息输出为作者警告信息,通常用于显示一些重要的警告信息.
  • SEND_ERROR:将消息输出为错误信息,并终止构建过程.
  • FATAL_ERROR:将消息输出为致命错误信息,并终止构建过程.
  1. message指令示例:
message("Hello, CMake!") # 输出普通消息

set(variable "world")
message("Hello, ${variable}!") # 输出包含变量的消息

message(STATUS "This is a status message") # 输出状态信息

message(WARNING "This is a warning") # 输出警告信息

message(FATAL_ERROR "This is a fatal error") # 输出致命错误并终止构建过程

2. CMake 语法的基本指令_第2张图片

2.2.2 CMake 的预定义宏

  1. CMake 预定义的宏是在 CMake 构建系统中预先定义的一些宏变量, 它们提供了有关构建环境和选项的信息, 用于指定源代码文件、目标输出路径、编译选项等, 预定义宏变量在 CMake 中是只读的,不能修改其值.

  2. 常用的 CMake 预定义宏:

  • CMAKE_SOURCE_DIR:表示CMakeLists.txt所在的顶级源代码目录的路径.

  • CMAKE_BINARY_DIR:表示当前构建目录(编译目录)的路径.

  • CMAKE_CURRENT_SOURCE_DIR:表示当前处理的CMakeLists.txt所在的源代码目录的路径.

  • CMAKE_CURRENT_BINARY_DIR:表示当前处理的CMakeLists.txt所在的构建目录的路径.

  • CMAKE_CURRENT_LIST_DIR:表示当前处理的CMakeLists.txt文件所在的完整路径.

  • CMAKE_MODULE_PATH:表示用于查找 CMake 模块文件的路径,可以将自定义的模块文件放置在该路径下.

  • CMAKE_C_COMPILERCMAKE_CXX_COMPILER:表示用于编译 C 和 C++代码的编译器路径.

  • CMAKE_C_FLAGS CMAKE_CXX_FLAGS:表示编译 C 和 C++代码时使用的编译选项.

  1. 打印 CMake 预定义宏,观察结果:
cmake_minimum_required(VERSION 3.0)
project(TEST)

# 打印每个预定义宏的值
message("CMAKE_SOURCE_DIR: ${CMAKE_SOURCE_DIR}")
message("CMAKE_BINARY_DIR: ${CMAKE_BINARY_DIR}")
message("CMAKE_CURRENT_SOURCE_DIR: ${CMAKE_CURRENT_SOURCE_DIR}")
message("CMAKE_CURRENT_BINARY_DIR: ${CMAKE_CURRENT_BINARY_DIR}")
message("CMAKE_CURRENT_LIST_DIR: ${CMAKE_CURRENT_LIST_DIR}")
message("CMAKE_MODULE_PATH: ${CMAKE_MODULE_PATH}")
message("CMAKE_C_COMPILER: ${CMAKE_C_COMPILER}")
message("CMAKE_CXX_COMPILER: ${CMAKE_CXX_COMPILER}")
message("CMAKE_C_FLAGS: ${CMAKE_C_FLAGS}")
message("CMAKE_CXX_FLAGS: ${CMAKE_CXX_FLAGS}")

2. CMake 语法的基本指令_第3张图片

2.3 CMake 的变量

就行一门编程语言一样,之前的函数和输出指令就像学习 C/C++的 print 和#include一样,同样 CMake 也具有变量的概念,方便用户操作这些变量,完成对项目的编译.

2.3.1 定义变量 set 指令

  1. set 指令用于定义变量, 语法如下:set( [CACHE [FORCE]])
  • :变量名,可以是任意有效的变量名.
  • :变量的值,可以是一个字符串、路径、列表、布尔值等.
  • CACHE [FORCE]:可选参数,用于定义一个缓存变量. 缓存变量可以在命令行或 CMake GUI 中修改; 指定变量的类型; 为变量提供一个描述性字符串; FORCE 选项可用于强制设置缓存变量的值.
cmake_minimum_required(VERSION 3.0)
project(TEST)

# 定义一个普通变量
set(MY_VARIABLE "Hello, CMake!")

# 定义一个路径变量
set(MY_PATH /path/to/some/directory)

# 定义一个列表变量
set(MY_LIST item1 item2 item3)

# 定义一个布尔变量
set(MY_FLAG TRUE)

# 使用 message 指令输出变量的值
message("MY_VARIABLE: ${MY_VARIABLE}")
message("MY_PATH: ${MY_PATH}")
message("MY_LIST: ${MY_LIST}")
message("MY_FLAG: ${MY_FLAG}")

2.3.2 字符串变量值的增加操作

  1. set指令进行字符串变量的拼接:set( "${} ") 在原有字符串变量的基础上拼接新字符串;
set(MY_STRING "Hello")
set(MY_STRING "${MY_STRING} CMake!")

2.3.3 路径变量值的增加操作

在 CMake 中可以使用set指令和file指令实现对路径变量的增加

  1. set 指令进行路径变量的拼接:set( "/")形式直接将两个路径拼接在一起.
set(MY_PATH "/path/to/some/directory")
set(MY_PATH "${MY_PATH}/subdirectory")
  1. 举例:
cmake_minimum_required(VERSION 3.0)
project(TEST)

# 使用 set 指令进行路径变量的拼接
set(MY_PATH_ORIGIN ${CMAKE_SOURCE_DIR})
set(MY_PATH_TEST "${MY_PATH_ORIGIN}/subdirectory")
set(MY_PATH_SRC ${MY_PATH_ORIGIN}/src)

# 使用 message 指令输出结果
message("MY_PATH_TEST: ${MY_PATH_TEST}")
message("MY_PATH_SRC: " ${MY_PATH_SRC})

2. CMake 语法的基本指令_第4张图片

2.3.4 列表变量值的增加操作

在 CMake 中,可以使用 setlist 命令对列表变量进行增加操作.

  1. 使用 set 命令对变量进行增加操作:
  • set( ) 语法来设置一个变量的值。如果该变量已经存在,它的值将被覆盖;
  • set( ${} ) 形式来在原有值的基础上追加新值;
set(MY_LIST item1 item2) # 设置一个列表变量
set(MY_LIST ${MY_LIST} item3) # 在原有列表变量的基础上追加新元素
  1. 使用 list 命令对变量进行增加操作:
  • list(APPEND [ ...]) 向列表变量中追加一个或多个新值.
set(MY_LIST item1 item2) # 设置一个列表变量
list(APPEND MY_LIST item3) # 向列表变量中追加新元素
  1. 示例
cmake_minimum_required(VERSION 3.0)
project(TEST)

add_executable(test main.c hex.h)
target_link_libraries(test m)
cmake_minimum_required(VERSION 3.0)
project(TEST)

# 设置变量
set(MY_LIST item1 item2)
set(MY_LIST ${MY_LIST} item3)
# 使用 message 函数输出结果
message("MY_LIST: ${MY_LIST}")

# 使用 list 命令对变量进行增加操作
set(MY_OTHER_LIST itemA itemB)
list(APPEND MY_OTHER_LIST itemC)
# 使用 message 函数输出结果
message("MY_OTHER_LIST: ${MY_OTHER_LIST}")

2. CMake 语法的基本指令_第5张图片

2.3.5 路径变量回到上一级

在 CMake 中,使用get_filename_component函数结合DIRECTORY选项来实现: get_filename_component( ${} DIRECTORY)

cmake_minimum_required(VERSION 3.0)
project(TEST)

set(MY_PATH "${CMAKE_SOURCE_DIR}")

get_filename_component(MY_PARENT_DIR ${MY_PATH} DIRECTORY)

message("MY_PARENT_DIR: ${MY_PARENT_DIR}")

2. CMake 语法的基本指令_第6张图片

2.3.6 列表变量删除元素

使用list(REMOVE_ITEM )命令来删除一个列表中的元素。该命令将从列表中删除指定的元素

cmake_minimum_required(VERSION 3.0)
project(TEST)

# 定义一个包含元素的列表
set(MY_LIST "apple" "banana" "orange" "grape")

# 输出原始列表
message("Original list: ${MY_LIST}")

# 删除元素
list(REMOVE_ITEM MY_LIST "banana")

# 输出修改后的列表
message("Modified list: ${MY_LIST}")

2. CMake 语法的基本指令_第7张图片

2.4 CMake 文件操作

CMake 主要是对 C/C++项目进行管理, 因此它最需要的是具有对文件的操作能力,例如读取到项目中的.c/.cpp/.h/.hpp/.xxx 文件; 或者是重命名等,这里重点还是介绍搜索文件的能力.

2.4.1 file 指令

file指令的用法示例:

Reading
  file(READ <filename> <out-var> [...])
  file(STRINGS <filename> <out-var> [...])
  file(<HASH> <filename> <out-var>)
  file(TIMESTAMP <filename> <out-var> [...])
  file(GET_RUNTIME_DEPENDENCIES [...])

Writing
  file({WRITE | APPEND} <filename> <content>...)
  file({TOUCH | TOUCH_NOCREATE} [<file>...])
  file(GENERATE OUTPUT <output-file> [...])
  file(CONFIGURE OUTPUT <output-file> CONTENT <content> [...])

Filesystem
  file({GLOB | GLOB_RECURSE} <out-var> [...] [<globbing-expr>...])
  file(MAKE_DIRECTORY [<dir>...])
  file({REMOVE | REMOVE_RECURSE } [<files>...])
  file(RENAME <oldname> <newname> [...])
  file(COPY_FILE <oldname> <newname> [...])
  file({COPY | INSTALL} <file>... DESTINATION <dir> [...])
  file(SIZE <filename> <out-var>)
  file(READ_SYMLINK <linkname> <out-var>)
  file(CREATE_LINK <original> <linkname> [...])
  file(CHMOD <files>... <directories>... PERMISSIONS <permissions>... [...])
  file(CHMOD_RECURSE <files>... <directories>... PERMISSIONS <permissions>... [...])

Path Conversion
  file(REAL_PATH <path> <out-var> [BASE_DIRECTORY <dir>] [EXPAND_TILDE])
  file(RELATIVE_PATH <out-var> <directory> <file>)
  file({TO_CMAKE_PATH | TO_NATIVE_PATH} <path> <out-var>)

Transfer
  file(DOWNLOAD <url> [<file>] [...])
  file(UPLOAD <file> <url> [...])

Locking
  file(LOCK <path> [...])

Archiving
  file(ARCHIVE_CREATE OUTPUT <archive> PATHS <paths>... [...])
  file(ARCHIVE_EXTRACT INPUT <archive> [...])
  1. 复制文件:file(COPY ...): 做个了解.

  2. 删除文件: file(REMOVE ...): 做个了解.

  3. 创建目录: file(MAKE_DIRECTORY ...): 做个了解

  4. 获取指定文件夹下的文件并存入变量: file(GLOB ...): 将指定目录下的搜索文件存储到一个变量中,其中匹配的规则可以是通配符模式,也可以采用正则表达式.

  5. 遍历获取文件并存入变量: file(GLOB_RECURSE ...): 遍历某个文件夹下的文件,将搜索文件存储到一个变量中.

cmake_minimum_required(VERSION 3.0)
project(TEST)

file(GLOB CMAKE_DIR_FILES ${CMAKE_SOURCE_DIR}/CMakeFiles/*.cmake)
message("RESULT: ${CMAKE_DIR_FILES}")

file(GLOB_RECURSE CMAKE_DEEP_FILES ${CMAKE_SOURCE_DIR}/CMakeFiles/*.cmake)
message("RESULT: ${CMAKE_DEEP_FILES}")

2. CMake 语法的基本指令_第8张图片

2.4.2 其他指令

aux_source_directory在官网中划分为 CMake 的project commands.
官方 aux_source_directory 指导

aux_source_directory: 相当于搜索目录下的源文件,这个源文件的类型是.c/.cpp/.h/.hpp 或者是其他的脚本语言的后缀, 如果目录下没有这些脚本文件,则为空.

cmake_minimum_required(VERSION 3.0)
project(TEST)

aux_source_directory(${CMAKE_SOURCE_DIR}/CMakeFiles CMAK_NOT_NOW_FILES)
message("CMakeFiles RESULT: ${CMAK_NOT_NOW_FILES}")

aux_source_directory(${CMAKE_SOURCE_DIR} CMAKE_NOW_FILES)
message("NOW RESULT: ${CMAKE_NOW_FILES}")

2. CMake 语法的基本指令_第9张图片

2.5 CMake 的逻辑语法指令

简单介绍 CMake 工具的逻辑语句的命令的主要作用,这部分很类似于 C/C++代码中的for, if/else等等…, 用于控制流程、条件判断和循环迭代.

2.5.1 判断语句 if/else

  1. if/else 用法:
if(condition) # 如果条件为真,执行这里的代码
else() # 如果条件为假,执行这里的代码
endif()
  1. 示例, 判断当前操作系统的类型:
cmake_minimum_required(VERSION 3.0)
project(TEST)

if(WIN32)
message("Running on Windows")
elseif(APPLE)
message("Running on macOS")
elseif(UNIX)
message("Running on Linux")
else()
message("Sorry i dont know.")
endif()

2. CMake 语法的基本指令_第10张图片

2.5.2 循环语句 foreach

  1. foreach 命令用法:
foreach(var IN items) # 对每个元素执行这里的代码
endforeach()
  1. 示例:
set(LIST_ITEMS "apple" "banana" "orange")
foreach(item IN LISTS LIST_ITEMS)
message("Fruit: ${item}")
endforeach()

2. CMake 语法的基本指令_第11张图片

2.5.3 选项指令 option

  1. option命令用法, 与if/else语句的区别在于, option更适合用作配置操作的选择:
option(option_name "option_description" [initial_value])
  1. 示例:
cmake_minimum_required(VERSION 3.0)
project(TEST)

option(USE_FEATURE "Enable feature" ON)
if(USE_FEATURE)
message("Feature enabled")
else()
message("Feature disabled")
endif()

2. CMake 语法的基本指令_第12张图片

2.5.4 其他指令的主要功能

  • unset:用于取消设置变量.

  • set_directory_properties:用于设置目录属性.

  • set_property:用于设置属性的值.

  • site_name:用于设置或查询当前 CMake 脚本的源文件名.

  • mark_as_advanced:将变量标记为高级选项,使其在 GUI 中不可见.

  • math:提供了一些数学运算函数.

  • cmake_host_system_information:用于获取有关主机系统的信息,例如操作系统类型、处理器类型等.

  • cmake_language:用于指定 CMake 语言版本.

  • cmake_minimum_required:用于指定所需的最低 CMake 版本.

  • cmake_parse_arguments:用于解析命令行参数,并将其存储在变量中.

  • cmake_path:提供了一些与路径相关的函数,例如获取文件名、扩展名等.

  • cmake_policy:用于设置或查询 CMake 的策略.

  • block:用于定义一个代码块,可以在该块中定义变量、函数和其他 CMake 指令.

  • endblock:结束一个代码块.

  • configure_file:用于通过替换文件中的变量来生成新文件.

  • continue:用于跳过当前循环中的剩余代码,并继续下一次循环迭代.

  • break:用于终止当前正在执行的循环.

  • endforeach:结束一个 foreach 循环.

  • while:用于创建一个循环,只要条件为真,就会一直执行循环体中的代码.

  • endwhile:结束一个 while 循环.

  • function:用于定义一个函数.

  • endfunction:结束一个函数定义.

  • return:从函数中返回.

  • macro:用于定义一个宏.

  • endmacro:结束一个宏定义.

  • include:用于包含其他 CMake 脚本.

  • include_guard:用于防止多次包含同一个文件.

  • execute_process:用于在构建过程中执行外部进程.

  • find_filefind_libraryfind_packagefind_pathfind_program:用于在系统中查找文件、库、包、路径和可执行程序.

  • get_cmake_propertyget_directory_propertyget_filename_componentget_property:用于获取 CMake 属性和变量的值.

  • string:提供了一些与字符串相关的函数,例如截取、替换、转换等.

  • separate_arguments:用于将字符串参数分割为独立的参数.

  • variable_watch:用于在变量更改时触发自定义操作.

你可能感兴趣的:(其他问题,cmake)