CMake语法详解

CMake

概述

用于自动生成makefile的一种脚本语言
CMake用于生成平台特定版本的项目设置

in-source编译、out-of-source编译

https://www.cnblogs.com/52php/p/5681745.html
内部编译会生成了一些无法自动删除的中间文件,并和源码混在一起。
out-of-source build一般在源文件的顶层目录中 新建build目录,将生成的临时文件都放在build目录中,这样所有的临时文件 都会放在build目录下,不会对source有任何影响。想清除上次cmake进行的配置,直接删除build文件夹即可。
#CMake语法
##变量类型
https://www.cnblogs.com/ncuneugcj/p/9756324.html

CMake 变量包含 Normal Variables、Cache Variables、环境变量。
###Normal Variables
作用域:整个CMakeLists.txt 文件及子目录。
我们在子目录中如果想要修改父目录 CMake 文件包含的 Normal 变量。必须通过 set(… PARENT_SCOPE) 的方式。
子目录可以访问父目录中的Normal Variables。
子目录定义的normal变量(未在父目录中定义过),父目录可以直接引用,无需PARENT_SCOPE;

###Cache Variables
作用域:相当于一个全局变量,我们在同一个cmake工程中都可以使用。

CMakeCache.txt
所有的Cache变量都会出现在 CMakeCache.txt 文件中。这个文件是我们键入 cmake .命令后自动出现的文件。打开这个文件发现,CMake 本身会有一些默认的内置变量(只列出有使用过的内置变量)。例如:CMAKE_C_COMPILER、CMAKE_BUILD_TYPE等。可以自行查看。当然,我们自己定义的 Cache 变量也会出现在这个文件中。
环境变量
https://cmake.org/cmake/help/latest/variable/ENV.html
使用$ ENV {VAR}可以读取环境变量VAR。

内置变量
https://www.cnblogs.com/xianghang123/p/3556425.html
CMAKE_SOURCE_DIR
https://cmake.org/cmake/help/latest/variable/CMAKE_SOURCE_DIR.html
源码目录顶层
CMAKE_BINARY_DIR
https://cmake.org/cmake/help/latest/variable/CMAKE_SOURCE_DIR.html
编译目录顶层
如果是 in source 编译,指得就是工程顶层目录,如果是 out-of-source 编译,指的是工程编译发生的目录。
CMAKE_INSTALL_PREFIX
安装目录顶层
CMAKE_MODULE_PATH
是一个list,默认为空
这个变量用来定义自己的 cmake 模块所在的路径。如果你的工程比较复杂,有可能会自己编写一些 cmake 模块,这些 cmake 模块是随你的工程发布的,为了让 cmake 在处理CMakeLists.txt 时找到这些模块,你需要通过 SET 指令,将自己的 cmake 模块路径设置一下。
比如
SET(CMAKE_MODULE_PATH KaTeX parse error: Double subscript at position 197: …进行代码最小化 CMAKE_C_̲FLAGS 传给C编译器的编译…{CMAKE_EXE_LINKER_FLAGS} -Wl,–allow-shlib-undefined")
CMAKE_STATIC_LIBRARY_PREFIX
静态库的前缀
CMAKE_STATIC_LIBRARY_SUFFIX
静态库的后缀
CMAKE_ SHARED_LIBRARY_PREFIX
动态库的前缀
CMAKE_ SHARED_LIBRARY_SUFFIX
动态库的后缀
在linux下的默认值好像不是”.so”

CMAKE_FIND_LIBRARY_SUFFIXES
查找库时要追加的后缀。
这指定当find_library()命令查找库时要添加到库名称的后缀。 在Windows系统上,这通常是.lib和.dll,这意味着在尝试查找foo库时,它将查找foo.dll等。
CMAKE_FIND_LIBRARY_PREFIXES
查找库时要添加的前缀。
这指定当find_library命令查找库时要添加到库名称的前缀。 在UNIX系统上,这通常是lib,这意味着在尝试查找foo库时,它将查找libfoo。
CMAKE_INCLUDE_PATH
用于通过FIND_FILE()和FIND_PATH()搜索的路径。

指定FIND_FILE()和FIND_PATH()都将使用的路径。 这两个命令将检查每个包含的目录是否存在当前正在搜索的文件。 默认情况下为空,旨在由项目设置。 另请参阅CMAKE_SYSTEM_INCLUDE_PATH,CMAKE_PREFIX_PATH。
CMAKE_LIBRARY_PATH
用分号分隔的目录列表,指定find_library()命令的搜索路径。 默认情况下为空,旨在由项目设置。 另请参阅CMAKE_SYSTEM_LIBRARY_PATH和CMAKE_PREFIX_PATH。
CMAKE_CXX_STANDARD
CMake 3.1引入
设置对C++新版本的特性支持。
支持的值是98,11,14,17,和20。
需要将其写在顶级CMakeLists.txt文件中,或者将其放在定义任何新目标之前
CMAKE_CXX_STANDARD_REQUIRED
CMake 3.1引入
如果将此属性设置为ON,则 CXX_STANDARD目标属性必须设置。
如果将此属性设置为OFF或未设置,则CXX_STANDARD目标属性被视为可选属性,并且如果请求的属性不可用,则可能会“衰减”到先前的标准。

交叉编译相关内置变量
https://cmake.org/cmake/help/v3.5/manual/cmake-toolchains.7.html#cross-compiling-for-linux
CMAKE_TOOLCHAIN_FILE
此变量在与cmake交叉编译时在命令行中指定。它是在cmake运行早期读取的文件的路径,指定编译器和工具链实用程序以及其他目标平台和编译器相关信息的位置。
https://www.cnblogs.com/rickyk/p/3875334.html
https://gitlab.kitware.com/cmake/community/wikis/doc/cmake/CrossCompiling
https://cmake.org/cmake/help/v3.5/manual/cmake-toolchains.7.html#cross-compiling

CMAKE_TOOLCHAIN_FILE不知道在哪里被引用?
实测,CMAKE_TOOLCHAIN_FILE会在编译前期被不停的调用
在CMAKE_TOOLCHAIN_FILE中修改的变量会覆盖掉cmakelists.txt中的变量
CMAKE_SYSTEM_NAME
即你目标机target所在的操作系统名称,比如ARM或者Linux你就需要写"Linux",如果Windows平台你就写"Windows",如果你的嵌入式平台没有相关OS你即需要写成"Generic",只有当CMAKE_SYSTEM_NAME这个变量被设置了,CMake才认为此时正在交叉编译,它会额外设置一个变量CMAKE_CROSSCOMPILING为TRUE.
CMAKE_C_COMPILER
顾名思义,即C语言编译器,这里可以将变量设置成完整路径或者文件名,设置成完整路径有一个好处就是CMake会去这个路径下去寻找编译相关的其他工具比如linker,binutils等,如果你写的文件名带有arm-elf等等前缀,CMake会识别到并且去寻找相关的交叉编译器。
CMAKE_CXX_COMPILER
同上,此时代表的是C++编译器。
CMAKE_SYSROOT
等同与编译器的-sysroot选项(实测)
设置CMAKE_C_COMPILER后不必设置CMAKE_SYSROOT,也会用toolchain的系统目录(实测)
CMAKE_FIND_ROOT_PATH(尽量避免使用,用file(GLOB_RECURSE…)替代)
https://www.cnblogs.com/rickyk/p/3875334.html
https://blog.csdn.net/weicao1990/article/details/51149412
设置Find_xxx命令的额外搜索目录的根路径。
比如你设置了/opt/arm/,所有的Find_xxx命令都会优先到这个路径下进行查找,再去系统目录(及CMAKE_INCLUDE_PATH、CMAKE_LIBRARY_PATH设置的目录)进行查找,如果你有一些库是不被包含在/opt/arm里面的,你也可以显示指定多个值给CMAKE_FIND_ROOT_PATH,比如
set(CMAKE_FIND_ROOT_PATH /opt/arm /opt/inst)
默认情况下,CMAKE_FIND_ROOT_PATH为空。
仅对Find_xxx命令有效,并不会修改LINK_DIRECTORIES和INCLUDE_DIRECTORIES (确定),也不会修改CMAKE_INCLUDE_PATH、CMAKE_LIBRARY_PATH等内置变量
CMAKE_FIND_ROOT_PATH_MODE_PROGRAM
对FIND_PROGRAM()起作用,有三种取值,NEVER,ONLY,BOTH,第一个表示不在你CMAKE_FIND_ROOT_PATH下进行查找,第二个表示只在CMAKE_FIND_ROOT_PATH路径下查找,第三个表示先查找CMAKE_FIND_ROOT_PATH路径,再查找系统目录(及CMAKE_INCLUDE_PATH、CMAKE_LIBRARY_PATH设置的目录)。在大多数情况下,find_program()用于搜索将要执行的可执行文件,例如使用execute_process()或add_custom_command()。因此,在大多数情况下,需要来自构建主机的可执行文件(sdk中也没有),因此通常将cmake_find_root_path_mode_program设置为never。
默认值为BOTH(实测)
会影响在find_path中的附加路径中的查找(实测)。
CMAKE_FIND_ROOT_PATH_MODE_LIBRARY
对FIND_LIBRARY()起作用,表示在链接的时候的库的相关选项,因此这里需要设置成ONLY来保证我们的库是在交叉环境CMAKE_FIND_ROOT_PATH中找的
CMAKE_FIND_ROOT_PATH_MODE_INCLUDE
对FIND_PATH()和FIND_FILE()起作用,一般来说也是ONLY
CMAKE_CROSSCOMPILING
如果CMake是交叉编译,则CMake将此变量自动设置为true。即如果预设了CMAKE_SYSTEM_NAME,则CMAKE_CROSSCOMPILING自动设置为TRUE,因此可以用于在CMake文件中进行测试。
property
属性的作用其实和变量查不多。每个属性都有其对应的作用。不能新建属性。
https://blog.csdn.net/darkdong/article/details/6103390
可以拥有属性(property)的域有以下几种:
源文件(source file)
目录(directory)
target
全局属性(global)

属性列表: https://cmake.org/cmake/help/latest/manual/cmake-properties.7.html#properties-on-targets
目录属性
猜测,目录属性会应用到目录下的所有目标的对应属性上。
目标属性
INTERFACE_INCLUDE_DIRECTORIES和INCLUDE_DIRECTORIES(生效)
https://stackoverflow.com/questions/52059777/what-is-the-difference-between-include-directories-and-interface-include-directo
INCLUDE_DIRECTORIES不会递归包含其子目录中的头文件(实测)。
可执行目标
可以将INCLUDE_DIRECTORIES属性设置为编译此目标文件所需的目录列表
不能设置INTERFACE_INCLUDE_DIRECTORIES,因为其他目标不能依赖于可执行目标(我不确定)
图书馆目标
可以将INCLUDE_DIRECTORIES属性设置为编译此目标文件所需的目录列表
可以将INTERFACE_INCLUDE_DIRECTORIES设置为编译依赖于此目标的其他目标所需的目录列表
接口目标
无法设置INCLUDE_DIRECTORIES属性,因为它永远不会被编译
最有可能设置INTERFACE_INCLUDE_DIRECTORIES,因为它只包含头文件,因此依赖的其他目标需要包含这些头
LINK_DIRECTORIES(未生效)
链接器搜索目录列表
function自定义函数
function( [ …])

endfunction()
cmake中的宏(macro)和函数(function)都支持动态参数
变量ARGC记录传入的参数个数
变量ARGV0,ARGV1,…顺序代表传入的参数
变量ARGV则是一个包含所有传入参数的list
变量ARGN也是一个包含传入参数的list,但不是所有参数,而是指macro/function声明的参数之后的所有传入参数
macro
macro( [ …])

endmacro()

eg:

定义一个宏 hello

macro(hello MESSAGE)
message(${MESSAGE})
endmacro()

调用宏 hello

hello(“hello world”)
macro和自定义函数比较
https://cmake.org/cmake/help/latest/command/macro.html
函数会为变量创建一个局部作用域,而宏则使用全局作用域

macro命令与function()命令非常相似。 尽管如此,还是存在一些重要的差异。
在函数中,ARGN,ARGC,ARGV和ARGV0,ARGV1,…是通常CMake意义上的真实变量。 在宏中,它们不是,它们是字符串替换,就像C预处理器与宏一样。 这有很多后果,如下面的Argument Caveats部分所述。
宏和函数之间的另一个区别是控制流。 通过将控制从调用语句转移到函数体来执行函数。 执行宏就像粘贴宏体代替调用语句一样。 这导致宏体中的return()不仅仅终止宏的执行; 相反,从宏调用的范围返回控制。 为避免混淆,建议完全避免在宏中使用return()。
CMake命令(内置函数)
https://elloop.github.io/tools/2016-04-10/learning-cmake-2-commands

set
指令功能: 用来显式的定义变量
set可以设置多个,即set( …)
set( … [PARENT_SCOPE])
Set Normal Variable
PARENT_SCOPE:我们在子目录中如果想要修改父目录 CMake 文件包含的 Normal 变量。必须通过 set(… PARENT_SCOPE) 的方式(如果是子目录中新定义的Normal变量,则无需PARENT_SCOPE,父目录也能使用)。设置PARENT_SCOPE后,变量值的先前状态在当前范围内保持不变,即只对父目录有效(例如,如果之前未定义,则仍未定义,如果它具有值,则仍为该值)。
eg:
1,set(libs " C M A K E S O U R C E D I R / s r c / m a i n / j n i l i b s " ) 这 个 命 令 完 成 了 这 么 一 件 事 情 : 定 义 了 一 个 变 量 l i b s , 并 且 变 量 的 值 为 {CMAKE_SOURCE_DIR}/src/main/jnilibs") 这个命令完成了这么一件事情: 定义了一个变量libs,并且变量的值为 CMAKESOURCEDIR/src/main/jnilibs")libs{CMAKE_SOURCE_DIR}/src/main/jnilibs,其中CMAKE_SOURCE_DIR 是一个cmake内置变量,指定了CMakeLists.txt所在的目录
set( … CACHE [FORCE])
Set Cache Entry
必须将指定为一行文本,提供快速摘要。
所存入变量在CMake GUI中的类型,被CMake GUI用来选择一个窗口(不使用CMake GUI,则这个参数随便设一个就行),让用户设置值。必须设为下述值中的一个:
FILEPATH = 文件选择对话框。
PATH = 路径选择对话框。
STRING = 任意的字符串。
BOOL = 布尔值选择复选框。
INTERNAL = 不需要GUI输入端。(适用于永久保存的变量)。
由于缓存条目旨在提供用户可设置的值,因此默认情况下不会覆盖现有的缓存条目。使用FORCE选项覆盖现有条目
set(ENV{} [])
Set Environment Variable
CACHE
https://cmake.org/cmake/help/v3.0/command/set.html
如果存在CACHE,则将被放入缓存中,除非它已经在缓存中。如果使用CACHE,则需要和。 CMake GUI使用来选择用户设置值的小部件。 的值可以是其中之一:
FILEPATH = File chooser dialog.
PATH = Directory chooser dialog.
STRING = Arbitrary string.任意字符串
BOOL = Boolean ON/OFF checkbox.
INTERNAL = No GUI entry (used for persistent variables).
通常,set(… CACHE …)会创建缓存变量,但由于缓存项是为了提供用户可设置的值,默认情况不会覆盖现有的缓存变量。 如果指定了FORCE,则强制修改缓存变量的值,即使该变量已在缓存中。 通常应该避免这种情况,因为它将删除用户对缓存变量值的任何更改。
unset
unset( [CACHE | PARENT_SCOPE])
取消设置变量,缓存变量或环境变量。
从当前作用域中删除一个普通变量,使其变为未定义状态。如果CACHE存在,则将删除一个缓存变量,而不是普通变量。
PARENT_SCOPE同set部分
设置环境变量
set(ENV{} …)
作用域是?实测不是终端作用域!
add_subdirectory
add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL])
向构建添加子目录。 source_dir指定源CMakeLists.txt和代码文件所在的目录。如果它是相对路径,它将根据当前目录(典型用法)进行评估,但它也可能是绝对路径。
list
https://blog.csdn.net/fuyajun01/article/details/9036477
LENGTH          返回list的长度
GET           返回list中index的element到value中
list(APPEND [ …])
APPEND         添加新element到list中
FIND           返回list中element的index,没有找到返回-1
INSERT           将新element插入到list中index的位置
REMOVE_ITEM      从list中删除某个element
REMOVE_AT       从list中删除指定index的element
REMOVE_DUPLICATES 从list中删除重复的element
REVERSE         将list的内容反转
SORT           将list按字母顺序排序
include
用来引用cmake模块,当引用时,会执行cmake模块中的内容。注意cmake模块与调用它的文件是同级的目录,并不是子目录。
camke模块是一个.cmake文件
eg:
在CMAKE_MODULE_PATH中添加路径 “ P O R T I N G P L A T F O R M D I R / c

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值