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 m a k e " , 该 路 径 下 有 一 个 p l a t f o r m − c o n f i g . c m a k e 文 件 l i s t ( A P P E N D C M A K E M O D U L E P A T H " {PORTING_PLATFORM_DIR}/cmake",该路径下有一个platform-config.cmake文件 list(APPEND CMAKE_MODULE_PATH " PORTINGPLATFORMDIR/cmake"platformconfig.cmakelist(APPENDCMAKEMODULEPATH"{PORTING_PLATFORM_DIR}/cmake”)
在CMAKE_MODULE_PATH中的全部路径中搜索名为platform-config、后缀为cmake的文件并执行
include(platform-config)
include_directories
将目录添加到当前CMakeLists文件的INCLUDE_DIRECTORIES目录属性中,相当于g++选项中的-I参数的作用
include_directories([AFTER|BEFORE] [SYSTEM] dir1 [dir2 …])
把dir1, [dir2 …]这(些)个路径添加到当前CMakeLists及其子CMakeLists的INCLUDE_DIRECTORIES目录属性中;
AFTER 或者 BEFORE 指定了要添加的路径是添加到原有包含列表之前或之后
若指定 SYSTEM 参数,则把被包含的路径当做系统包含路径来处理
eg: include_directories(./include)
作用:把当前目录(CMakeLists.txt所在目录)下的include文件夹加入到头文件包含路径中
target_include_directories
将目录添加到目标的INCLUDE_DIRECTORIES或INTERFACE_INCLUDE_DIRECTORIES属性中。
target_include_directories( [SYSTEM] [BEFORE]
[items1…]
[ [items2…] …])

INTERFACE,PUBLIC和PRIVATE关键字用来指定[item]参数的范围。 PRIVATE和PUBLIC项将[item]填充到的INCLUDE_DIRECTORIES属性。 PUBLIC和INTERFACE项将[item]填充到的INTERFACE_INCLUDE_DIRECTORIES属性。

eg: target_include_directories(prime-video-device-layer-interface INTERFACE include)
作用:把当前目录(CMakeLists.txt所在目录)下的include文件夹添加到prime-video-device-layer-interface的INTERFACE_INCLUDE_DIRECTORIES属性中
aux_source_directory(弃用)
aux_source_directory(

)
该命令会把参数 中所有的源文件名称赋值给变量
没啥用,直接set也能设置啊。不对set设置的是文件夹,而aux_source_directory能设置文件夹中的各个文件名
这个命令不好用啊
aux_source_directory 不会递归包含子目录,仅包含指定的dir目录
CMake官方不推荐使用aux_source_directory及其类似命令(file(GLOB_RECURSE …))来搜索源文件
add_library
https://www.cnblogs.com/coderfenghc/archive/2012/06/23/2559603.html
使用指定的源文件编译生成链接文件(即库文件)
Normal Libraries
add_library( [STATIC | SHARED | MODULE]
[EXCLUDE_FROM_ALL]
[source1] [source2 …])
表示库文件的名字, 对应于逻辑目标名称,而且在一个工程的全局域内必须是唯一的。待构建的库文件的实际文件名根据对应平台的命名约定来构造(比如lib.a或者.lib)。
指定STATIC,SHARED,或者MODULE参数用来指定要创建的库的类型。
STATIC: 静态库。
SHARED:动态库。
MODULE:(不准)模块库是没有链接到其他目标的插件,但是可以在运行时使用类dlopen功能动态加载

默认情况下,库文件创建于: 编译目录/{CMakelists.txt在源码目录中的相对位置}
看关于目标属性ARCHIVE_OUTPUT_DIRECTORY, LIBRARY_OUTPUT_DIRECTORY, and RUNTIME_OUTPUT_DIRECTORY 的文档来改变位置. 看目标属性 OUTPUT_NAME的文档来改变最终生成的库文件的名字.
eg:

外部项目prime-video-device-layer-project的编译目录为:build/linux/RelWithDebInfo/device-layer/prime-video-device-layer-project-prefix/src/prime-video-device-layer-project-build
此CMakelists.txt在源码目录中的相对位置为src/media-pipeline-backend/(linux-device-layer/implementation/为外部项目根目录)
故生成的静态链接库位于:

build/linux/RelWithDebInfo/device-layer/prime-video-device-layer-project-prefix/src/prime-video-device-layer-project-build/src/media-pipeline-backend/libmediapipelinebackendimpl_drm.a
Interface Libraries
add_library( INTERFACE [IMPORTED [GLOBAL]])
创建接口库目标
INTERFACE库目标编译时不会产生任何内容 (即不会生成任何库),但可以在其上设置属性,并且可以安装,导出和导入。

Imported Libraries
add_library( IMPORTED
[GLOBAL])
引用位于外部项目中的库文件(不会生成新的库文件),使其可以像在项目中构建的任何目标一样被正常引用,不会生成任何规则来构建它。
eg:

add_dependencies
add_dependencies( []…)
在顶级目标之间添加依赖关系。
使顶级依赖于其他顶级目标,以确保它们在之前构建。 顶级目标是由add_executable(),add_library()或add_custom_target()命令之一创建的目标(但不是由CMake生成的目标,如install)。
一般来说用不到这个命令。用到的情况就是两个targets有依赖关系(通过target_link_libraries解决)并且依赖库也是通过编译源码产生的。这时候一句add_dependencies可以在直接编译上层target时,自动检查下层依赖库是否已经生成。没有的话先编译下层依赖库,然后再编译上层target,最后link depend target。
https://www.cnblogs.com/wpcockroach/p/6625699.html

add_executable
https://blog.csdn.net/sjt19910311/article/details/51660251
add_executable( [WIN32] [MACOSX_BUNDLE]
[EXCLUDE_FROM_ALL]
[source1] [source2 …])
使用指定的源文件编译生成一个名为的可执行文件。

target_compile_options
添加编译选项(就是gcc的那些编译选项)到目标。
target_compile_options( [BEFORE]
[items1…]
[ [items2…] …])
在编译给定目标文件时,指定要用到的编译选项。target目标文件必须已经存在(由命令add_executable()或add_library()创建)且不能被IMPORTED修饰。
参数:
1.若指定BEFORE修饰,则内容会被前缀到属性。
2.该命令可用来添加任何选项,但是也存在其他可选的命令来添加到预处理(target_compile_definitions()和add_definitions())或包含目录(target_include_directories()和include_directories())。
3.关键字INTERFACE,PUBLIC和PRIVATE指定后续参数作用域。PRIVATE和PUBLIC项会填充到target目标文件的COMPILE_OPTIONS属性。PUBLIC和INTERFACE项会被填充到target目标文件INTERFACE_COMPILE_OPTIONS属性。后续参数指定编译选项。对同一个target文件的重复调用按调用顺序进行。

link_directories(不建议使用)
将链接目录添加到当前CMakeLists.txt文件的LINK_DIRECTORIES目录属性中。
link_directories([AFTER|BEFORE] directory1 [directory2 …])
指定链接器在链接给定目标时应在其中搜索库的路径。

很少需要此命令,在有其他选择的情况下应避免使用此命令。最好在可能的情况下将完整的绝对路径传递给库,因为这样可以确保始终链接正确的库。 find_library()命令提供了完整路径,通常可以直接在对target_link_libraries()的调用中使用。

实测,可以修改LINK_DIRECTORIES属性,但是LINK_DIRECTORIES属性不起作用
target_link_directories()(不建议使用)(3.13开始才有这个命令)
将链接目录添加到目标的LINK_DIRECTORIES属性中。
target_link_directories( [BEFORE]
[items1…]
[ [items2…] …])
命名的必须由诸如add_executable()或add_library()之类的命令创建,并且不能为ALIAS目标。

很少需要此命令,在有其他选择的情况下应避免使用此命令。最好通过find_library()命令将完整的绝对路径传递给target_link_libraries,因为这样可以确保始终链接正确的库。
link_libraries(不建议使用)
将库链接到以后添加的所有目标。
link_libraries([item1 [item2 […]]]
[[debug|optimized|general] ] …)
应尽可能使用target_link_libraries()命令。
target_link_libraries
将目标文件与库文件进行链接
target_link_libraries(

[ …]…)

是指通过add_executable()和add_library()指令生成已经创建的目标文件。
默认情况下,库依赖项是传递的。当这个目标链接到另一个目标时,链接到这个目标的库也会出现在另一个目标的连接线上。
(以下内容已确认)
https://www.jianshu.com/p/aaa19816f7ad
PRIVATE 只给自己用,不给依赖者用
PUBLIC 自己和依赖者都可以用
INTERFACE 自己不用,给依赖者用

INTERFACE详解: 将附加到链接接口,不会链接到中。
即当以后被链接到其他target中时,会把接口库也链接到中.而没有链接,不能使用中的资源。
库文件
可以为没有前缀、后缀的名字,也可以是-l(小写的L)没有前缀、后缀的名字。
动态库、静态库均可链接。当省略后缀时,默认优先链接动态库。
当为不带路径的lib时,会在系统目录和目标的LINK_DIRECTORIES(实测不会)下寻找这个lib。
不可以是绝对路径的名字(实测)
如果不在系统查找路径,则需要在该前 加一个-LSDK目录(必须加-L 不然无意义)的,等效于gcc中的-L dir。(实测)

option
option( “” [value])
提供选项为ON或OFF的选项。 如果未提供初始,则使用OFF。 如果已设置为普通变量,则该命令不执行任何操作(仅在CMake 3.13及更高版本中,参考CMP0077)
eg:
定义一个变量TEST_DEBUG,并设为OFF
option(TEST_DEBUG “option for debug” OFF)
TEST_DEBUG为OFF,故不会执行if中的命令
if (TEST_DEBUG)

endif()
file
Reading
STRING
file(STRINGS […])
解析中的ASCII字符串列表,并将其存储在中。文件中的二进制数据将被忽略。回车符(\ r,CR)被忽略。
Filesystem
MAKE_DIRECTORY
file(MAKE_DIRECTORY [

…])
MAKE_DIRECTORY在指定目录处创建子目录,如果它们的父目录不存在,也会创建它们的父目录。
COPY
file({COPY | INSTALL} … DESTINATION […])
COPY表示复制文件,目录以及符号链接到一个目标文件夹中。输入路径将视为相对于当前源码目录的路径。目标路径则是相对于当前的构建目录。复制保留输入文件的一些权限属性
RENAME
file(RENAME )
重命名
GLOB
file(GLOB
[LIST_DIRECTORIES true|false] [RELATIVE ] [CONFIGURE_DEPENDS]
[…])
产生一个文件系统中与能与规则匹配成功的所有文件组成的列表并将它存储到变量 中。文件名替代表达式和正则表达式相似,但更简单。
如果LIST_DIRECTORIES设置为false,则目录将被省略
如果 RELATIVE 标志位被设定,则结果将作为相对于给定路径的相对路径返回。
结果将按字典顺序排序。
GLOB_RECURSE
file(GLOB_RECURSE [FOLLOW_SYMLINKS]
[LIST_DIRECTORIES true|false] [RELATIVE ] [CONFIGURE_DEPENDS]
[…])
同GLOB,只是多了可选参数[FOLLOW_SYMLINKS]
message
https://cmake.org/cmake/help/latest/command/message.html
在执行cmake命令时打印消息
message([] “message to display” …)
The optional keyword determines the type of message:
FATAL_ERROR
CMake Error, stop processing and generation.
SEND_ERROR
CMake Error, continue processing, but skip generation.
WARNING
CMake Warning, continue processing.
AUTHOR_WARNING
CMake Warning (dev), continue processing.
eg:
message(WARNING “WMY " ${ENTRY})
add_definitions
向 C/C++编译器添加-D 定义
project
project( […])
project(
[VERSION [.[.[.]]]]
[DESCRIPTION ]
[HOMEPAGE_URL ]
[LANGUAGES …])
设置项目的名称,并将其存储在变量PROJECT_NAME中。并设置变量:
PROJECT_SOURCE_DIR, _SOURCE_DIR
PROJECT_BINARY_DIR, _BINARY_DIR
从顶级CMakeLists.txt调用时,还会将项目名称存储在变量CMAKE_PROJECT_NAME中。
其他变量由以下描述的可选参数设置。 如果未使用任何这些参数,则将相应的变量设置为空字符串。
cmake_minimum_required
设置项目所需的cmake的最低版本
如果运行版本的CMake低于所需版本,它将停止处理项目并报告错误。
cmake_minimum_required(VERSION)会隐式调用cmake_policy(VERSION),从而将cmake的策略版本设置为VERSION版本。
cmake_policy
cmake_policy(VERSION […])
将cmake的策略版本设置为VERSION版本。
cmake_policy(SET CMP NEW)
用来设置CMake策略。
随着CMake的演变,有时为了搞定bug或改善现有特色的实现方法,改变现有的策略是必须的。每个策略被赋予一个"CMP"格式的识别符,其中”“是一个整数索引。可以告诉CMake对策略使用OLD或NEW行为。NEW行为即在当前版本或更高版本中定义的行为。OLD行为即之前版本定义的行为。
eg:
cmake_policy(SET CMP0063 NEW)
对策略0063采用新行为
string
string(TIMESTAMP [] [UTC])
将表示当前日期或时间的字符串写入。
如果命令无法获取时间戳,则输出变量将设置为空字符串“”。
选项UTC表示用UTC时间而不是用默认的本地时间
string(REPLACE …)
将所有在中出现的替换为,并将结果存储在中。
find_path(尽量避免使用,用file(GLOB_RECURSE…)替代)
find_path ( name1 [path1 path2 …])
该命令用于查找名为name1的头文件的所在目录。
一个名为的cache变量会被创建用来存储该命令的结果。如果该头文件被找到了,头文件的所在目录(而不是这个头文件的绝对路径)会存储在该变量中,搜索过程将不会继续(即不会全部找完,找到一个就返回),除非该变量被清除。如果没有找到,结果将会是-NOTFOUND。附加的搜索位置可以在[path1 path2 …]参数中指定。
这个命令的作用是判断能否找到名为name1的头文件。并把头文件的绝对路径存在中。这样就可以通过include_directories把添加到目标的INCLUDE_DIRECTORIES目标属性中来在目标中包含这个头文件及同目录下的其他头文件。
对于所有的path都不会在path子文件夹中查找(实测)。所以其实find_xxx()很垃圾很不好用!
对于CMAKE_FIND_ROOT_PATH设置的路径,仅会在该路径的/include、/usr/include目录下(不包含子目录)寻找头文件。(实测)
eg:
find_path(LIBEV_INCLUDE_DIR NAMES ev.h)
if(LIBEV_INCLUDE_DIR)
set(LIBEV_INCLUDE_DIRS L I B E V I N C L U D E D I R ) i n c l u d e d i r e c t o r i e s ( " {LIBEV_INCLUDE_DIR}) include_directories(" LIBEVINCLUDEDIR)includedirectories("{LIBEV_INCLUDE_DIRS}”)
endif()
find_library
find_library ( name1 [path1 path2 …])
该命令用来查找一个库文件。得到的是库文件的绝对路径,而不是库文件的目录的绝对路径(实测)。其他与find_path相同。
默认查找动态库
eg:
FIND_LIBRARY(lib_png png)
if(lib_png)
MESSAGE(lib_png “${lib_png}”)
target_link_libraries(ignite-platform INTERFACE KaTeX parse error: Expected 'EOF', got '#' at position 11: {lib_png})#̲需要加上lib的路径(含lib…{CMAKE_MODULE_PATH}中的所有目录。如果有,则执行该cmake文件从而找到包;如果没有,然后再查看它自己的模块目录 /share/cmake-x.y/Modules/ ($CMAKE_ROOT的具体值可以通过CMake中message命令输出)来寻找包。这称为模块模式。
2、 如果没找到这样的文件,find_package()会在~/.cmake/packages/或/usr/local/share/中的各个包目录中查找,寻找<库名字的大写>Config.cmake 或者 <库名字的小写>-config.cmake (比如库Opencv,它会查找/usr/local/share/OpenCV中的OpenCVConfig.cmake或opencv-config.cmake)。这称为配置模式。(没有用到这种模式,本地目录下也没有这样的包)

会自动定义一个 _FOUND变量并设置为指示是否找到包。
FindPkgConfig(PkgConfig)模块
https://cmake.org/cmake/help/latest/module/FindPkgConfig.html
是cmake中的一个模块,用来更好的查找模块
引用该模块:
find_package(PkgConfig)
搜索路径
AVPKV2采用的文档:https://autotools.io/pkgconfig/cross-compiling.html
https://ilgthegeek.wordpress.com/2015/02/05/pkg-config-search-path/
pkg-config的搜索路径由几个环境变量控制,其中包括
默认路径:
PKG_CONFIG_PATH:(猜测)就是PKG_CONFIG_DIR
PKG_CONFIG_DIR:列出其他搜索路径。但是不会覆盖默认路径
PKG_CONFIG_LIBDIR:当$PKG_CONFIG_LIBDIR被指定,它会覆盖默认的目录(如编译/usr/lib/pkgconfig)和PKG_CONFIG_DIR。
PKG_CONFIG_SYSROOT_DIR:设置sysroot目录

对于交叉编译,必须使用PKG_CONFIG_LIBDIR来确保没有把系统软件包引入到构建中。
pkg_check_modules函数
和pkg_search_module类似
pkg_search_module函数
是FindPkgConfig(PkgConfig)模块中的一个函数。
用于查找模块
pkg_search_module(
[REQUIRED] [QUIET]
[NO_CMAKE_PATH]
[NO_CMAKE_ENVIRONMENT_PATH]
[IMPORTED_TARGET [GLOBAL]]
[…])
参数说明:

输出结果的变量的前缀名。当该函数执行完成后,会生成如下变量:
当使–static选项时, = _STATIC;否则, = 。
_FOUND 如果存在模块,则设置为1
_LIBRARIES 仅库(不带“ -l”)
_LINK_LIBRARIES 库及其绝对路径
_LIBRARY_DIRS 库的路径(不带“ -L”)
_LDFLAGS 所有必需的链接器标志
_LDFLAGS_OTHER 所有其他链接器标志
_INCLUDE_DIRS 头文件及其绝对路径(不带’-I’)
_CFLAGS 所有必需的标志
_CFLAGS_OTHER 其他编译器标志

当只有一个时,为;当大于一个时,为_。
输出的变量:
_VERSION
模块的版本
_PREFIX
模块目录(不准,未使用)
_INCLUDEDIR
模块的头文件目录(不准,未使用)
_LIBDIR
模块的库文件目录(不准,未使用)
[REQUIRED]
如果没有查找到模块,该命令将失败并报错。
[QUIET]
不打印状态消息。

要查找的模块名。每个可以是裸模块名(即不带前后缀的模块名),或者它可以是一个模块名称与版本约束(支持运算符=、<、>、<=、>=),以下是一个名为foo的模块所具有的各种约束的示例:
foo 匹配任何版本。
foo<2 仅匹配2之前的版本。
foo>=3.1 匹配3.1或更高版本的任何版本。
foo=1.2.3 要求foo必须完全是版本1.2.3。
set_property
https://blog.csdn.net/fuyajun01/article/details/9036485
set_property( DIRECTORY [

] |
TARGET [ …] |
SOURCE [ …] |
INSTALL [ …] |
TEST [ …] |
CACHE [ …] >
[APPEND] [APPEND_STRING]
PROPERTY [value1 …])
在对应的域中设置命名属性。

第一个参数确定设置属性的范围。它必须是以下之一:
GLOBAL
范围是唯一的,不接受名称。
DIRECTORY
范围默认为当前目录,但另一个目录(已由CMake处理)可以通过完整或相对路径来命名。另请参阅set_directory_properties() 命令。
TARGET
范围可以命名零个或多个现有目标。另请参阅set_target_properties() 命令。
SOURCE
范围可以命名零个或多个源文件。请注意,源文件属性仅对添加到同一目录(CMakeLists.txt)中的目标可见。另请参阅set_source_files_properties() 命令。
INSTALL
待完善
TEST
范围可以命名为零个或多个现有测试。另请参阅set_tests_properties() 命令。
CACHE
范围必须命名零个或多个缓存现有条目。

如果给出了该选项APPEND,则该列表将附加到任何现有属性值之后。如果APPEND_STRING给定了选项,则将字符串作为字符串附加到任何现有的属性值之后,即,它导致更长的字符串而不是字符串列表。

必选项PROPERTY后面紧跟着要设置的属性的名字。
其他的参数用于构建以分号隔开的列表形式的属性值。
set_target_properties
set_target_properties(target1 target2 …
PROPERTIES prop1 value1
prop2 value2 …)
等同于域为TARGET的set_property(TARGET)
get_property
获取一个属性值,保存到中
get_property(
DIRECTORY [dir] |
TARGET |
SOURCE |
TEST |
CACHE |
VARIABLE>
PROPERTY
[SET | DEFINED |BRIEF_DOCS | FULL_DOCS])

相关域的说明与set_property意义相同。
configure_file
configure_file 的作用是让普通文件也能使用CMake中的变量,也就是说代码文件中可以使用CMake中的变量。
configure_file(
[COPYONLY] [ESCAPE_QUOTES] [@ONLY]
[NEWLINE_STYLE [UNIX|DOS|WIN32|LF|CRLF] ])
该命令替换掉在输入文件中,以 V A R 格 式 或 @ V A R @ 格 式 引 用 的 任 意 变 量 , 如 同 它 们 的 值 是 由 C M a k e 确 定 的 一 样 。 如 果 一 个 变 量 还 未 定 义 , 它 会 被 替 换 为 空 。 如 果 指 定 了 C O P Y O N L Y 选 项 , 那 么 变 量 就 不 会 展 开 。 如 果 指 定 了 E S C A P E Q U O T E S 选 项 , 那 么 所 有 被 替 换 的 变 量 将 会 按 照 C 语 言 的 规 则 被 转 义 。 该 文 件 将 会 以 C M a k e 变 量 的 当 前 值 被 配 置 。 如 果 指 定 了 @ O N L Y 选 项 , 只 有 @ V A R @ 格 式 的 变 量 会 被 替 换 而 {VAR}格式或@VAR@格式引用的任意变量,如同它们的值是由CMake确定的一样。 如果一个变量还未定义,它会被替换为空。如果指定了COPYONLY选项,那么变量就不会展开。如果指定了ESCAPE_QUOTES选项,那么所有被替换的变量将会按照C语言的规则被转义。该文件将会以CMake变量的当前值被配置。如果指定了@ONLY选项,只有@VAR@格式的变量会被替换而 VAR@VAR@CMakeCOPYONLYESCAPEQUOTESCCMake@ONLY@VAR@{VAR}格式的变量则会被忽略。这对于配置使用${VAR}格式的脚本文件比较有用。任何类似于#cmakedefine VAR的定义语句将会被替换为#define VAR或者/* #undef VAR */,视CMake中对VAR变量的设置而定。任何类似于#cmakedefine01 VAR的定义语句将会被替换为#define VAR 1或#define VAR 0,视VAR被评估为TRUE或FALSE而定。
execute_process
执行一个或多个子进程,可以用这条命令来执行系统命令。
execute_process(COMMAND []
[COMMAND []]…
WORKING_DIRECTORY
TIMEOUT
[RESULT_VARIABLE ]
…)

[RESULT_VARIABLE ]: 将variable设置为运行进程的结果。 这将是最后一个子进程的整数返回码或描述错误情况的字符串。
[RESULTS_VARIABLE ]:变量将被设置为以给定参数的顺序包含所有进程的结果,以 分号分隔的列表的形式出现COMMAND。每个条目都是对应子项的整数返回码或描述错误情况的字符串。
COMMAND
CMake直接使用操作系统API执行子进程。 所有参数都将VERBATIM传递给子进程。 没有使用中间shell,因此诸如>之类的shell操作符被视为普通参数。(使用INPUT_ *,OUTPUT_ *和ERROR_ *选项重定向stdin,stdout和stderr)
INCLUDE_DIRECTORIES
include_directories([AFTER|BEFORE] [SYSTEM] dir1 [dir2 …])
将< dir1>添加到当前CMakeLists文件的INCLUDE_DIRECTORIES目录属性、当前CMakeLists文件中每个目标的INCLUDE_DIRECTORIES目标属性中。
LINK_DIRECTORIES
link_directories([AFTER|BEFORE] directory1 [directory2 …])
将< directory1>添加到当前CMakeLists.txt文件的LINK_DIRECTORIES目录属性、当前CMakeLists文件中每个目标的LINK_DIRECTORIES目录属性中。
install
https://www.cnblogs.com/coderfenghc/archive/2012/08/12/2627561.html
指定在安装时要运行的规则

DESTINATION
指定安装路径(要安装到哪里的路径)。 如果给出了完整路径(带有前导斜杠或驱动器号),则直接使用它。 如果给出了相对路径,则相对于CMAKE_INSTALL_PREFIX变量的值进行解释。
FILES_MATCHING
指定匹配安装文件的条件,可以使用PATTERN或REGEX两种比对方式,要注意PATTERN会比对全路径而不只是文件名。
COMPONENT(没理解,说的不好)
指定了该安装规则相关的一个安装部件的名字,比如“runtime”或“development”。对于那些指定安装部件的安装过程来说,在安装时只有与给定的部件名相关的安装规则会被执行。对于完整安装,所有部件都会被安装。
RENAME
指定已安装文件的名称,该名称可能与原始文件不同。 仅当命令安装了单个文件时,才允许重命名。
OPTIONAL
如果要安装的文件不存在,指定这不是错误。
TARGETS版本的install命令
把targets复制到


install(TARGETS targets… [EXPORT ]
[[ARCHIVE|LIBRARY|RUNTIME|OBJECTS|FRAMEWORK|BUNDLE|
PRIVATE_HEADER|PUBLIC_HEADER|RESOURCE]
[DESTINATION ]
[PERMISSIONS permissions…]
[CONFIGURATIONS [Debug|Release|…]]
[COMPONENT ]
[RENAME ] [OPTIONAL])
目标类型(可选):
如果指定了目标类型,那么只有那种类型的目标会被安装。否则,所有目标都会被安装。目标类型参数的作用是根据目标类型不同把不同目标安装到不同DESTINATION。
ARCHIVE
静态库被视为ARCHIVE目标。
LIBRARY
模块库始终被视为LIBRARY目标。对于非DLL平台,共享库被视为LIBRARY目标。对于DLL平台,动态库的DLL部分被当做一个RUNTIME目标,而对应的导出库被当做是一个ARCHIVE目标。所有基于Windows的系统都是DLL平台。
RUNTIME
可执行文件被视为RUNTIME对象。

对于给定的每个参数,其后的参数仅适用于参数中指定的目标或文件类型。如果未给出,则 安装属性适用于所有目标类型。如果仅给出一个,则将仅安装该类型的目标(可用于仅安装DLL或仅导入库)。
在该命令的TARGETS版本的一次调用中,可以一次性指定一个或多个属性组。一个目标也可以被多次安装到不同的位置。假设有三个目标myExe,mySharedLib和myStaticLib,下面的代码

install(TARGETS myExe mySharedLib myStaticLib
        RUNTIME DESTINATION bin
        LIBRARY DESTINATION lib
        ARCHIVE DESTINATION lib/static)

install(TARGETS mySharedLib DESTINATION /some/full/path)
将会把myExe安装到/bin目录下,把myStaticLib安装到/lib/static目录下。在非-DLL平台上,mySharedLib将会被安装到/lib和/some/full/path下。在DLL平台上,mySharedLib DLL将会被安装到/bin和/some/full/path路径下,它的导出库会被安装到/lib/static和/some/full/path路径下。
eg:
install(TARGETS ${TARGET_NAME} LIBRARY DESTINATION lib)
DIRECTORY版本的install命令
把directory复制到


install(DIRECTORY targets… DESTINATION
[PERMISSIONS permissions…]
[CONFIGURATIONS [Debug|Release|…]]
[COMPONENT ]
[RENAME ] [OPTIONAL])

eg:
install(DIRECTORY “${ASSETS_DIR}/fonts” DESTINATION lib)
FILES版本的install命令
把files复制到


install(FILES files… DESTINATION
[PERMISSIONS permissions…]
[CONFIGURATIONS [Debug|Release|…]]
[COMPONENT ]
[RENAME ] [OPTIONAL])

eg:
install(FILES ${RUBY_PLAYER_LIBS} DESTINATION lib)
PROGRAMS版本的install命令
把files复制到


install(PROGRAMS files… DESTINATION
[PERMISSIONS permissions…]
[CONFIGURATIONS [Debug|Release|…]]
[COMPONENT ]
[RENAME ] [OPTIONAL])

PROGRAMS版本与FILES版本一样,只在默认权限上有所不同

TARGETS版本的install命令
https://cmake.org/cmake/help/v3.13/command/install.html#targets

install(TARGETS targets… [EXPORT ]
[[ARCHIVE|LIBRARY|RUNTIME|FRAMEWORK|BUNDLE|
PRIVATE_HEADER|PUBLIC_HEADER|RESOURCE]
[DESTINATION

]
[PERMISSIONS permissions…]
[CONFIGURATIONS [Debug|Release|…]]
[COMPONENT ]
[OPTIONAL] [NAMELINK_ONLY|NAMELINK_SKIP]
] […])

eg:
install(
TARGETS amazon_player
LIBRARY DESTINATION lib
RUNTIME DESTINATION lib
COMPONENT library)
猜测:把目标amazon_player安装到lib目录下,并更名为libamazon_player.so,同时将谁的component设为library
add_subdirectory
在构建中添加一个子目录。

add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL])
将一个子目录添加到构建中。source_dir指定源CMakeLists.txt和代码文件所在的目录。如果是相对路径,则将相对于当前目录(典型用法)进行评估,但也可能是绝对路径。

CMake将立即处理指定源目录中的CMakeLists.txt文件,然后继续执行当前输入文件中的命令。
configure_file
https://www.cnblogs.com/welhzh/p/11106864.html
将文件复制到另一个位置并修改其内容。使变量、宏定义可以通过cmake实现。
configure_file(
[COPYONLY] [ESCAPE_QUOTES] [@ONLY]
[NEWLINE_STYLE [UNIX|DOS|WIN32|LF|CRLF] ])
将文件拷贝到然后替换文件内容中引用到的变量值。
该命令替换掉在输入文件中,以KaTeX parse error: Expected 'EOF', got '#' at position 89: …变量的当前值被配置。任何类似于#̲cmakedefine VAR…{VAR}格式的变量则会被忽略。这对于配置使用${VAR}格式的脚本文件比较有用。
eg:

cmake_parse_arguments
https://www.cnblogs.com/gaox97329498/p/10991449.html
解析函数或宏的动态参数
cmake_parse_arguments(
…)
前缀, 解析出的参数都会按照 prefix_参数名 的形式形成新的变量;
: 如果中包含中设置的变量,则那个变量为 TRUE 反之为 FALSE
: 单值关键词列表,每个关键词仅仅对应一个值。如果中包含对应关键词的值,则该值被赋值,否则为
: 多值关键词列表,每个关键词可对应多个值。同上。
… 参数, 一般传入 A R G N 即 可 e g : m a c r o ( m y i n s t a l l ) s e t ( o p t i o n s O P T I O N A L F A S T ) s e t ( o n e V a l u e A r g s D E S T I N A T I O N R E N A M E ) s e t ( m u l t i V a l u e A r g s T A R G E T S C O N F I G U R A T I O N S ) c m a k e p a r s e a r g u m e n t s ( M Y I N S T A L L " {ARGN} 即可 eg: macro(my_install) set(options OPTIONAL FAST) set(oneValueArgs DESTINATION RENAME) set(multiValueArgs TARGETS CONFIGURATIONS) cmake_parse_arguments(MY_INSTALL " ARGNeg:macro(myinstall)set(optionsOPTIONALFAST)set(oneValueArgsDESTINATIONRENAME)set(multiValueArgsTARGETSCONFIGURATIONS)cmakeparsearguments(MYINSTALL"{options}" “ o n e V a l u e A r g s " " {oneValueArgs}" " oneValueArgs""{multiValueArgs}” ${ARGN} )
endmacro()
my_install(TARGETS foo bar DESTINATION bin OPTIONAL blub CONFIGURATIONS)
则对应的变量值为:
MY_INSTALL_OPTIONAL = TRUE
MY_INSTALL_FAST = FALSE # was not used in call to my_install
MY_INSTALL_DESTINATION = “bin”
MY_INSTALL_RENAME # was not used
MY_INSTALL_TARGETS = “foo;bar”
MY_INSTALL_CONFIGURATIONS # was not used
MY_INSTALL_UNPARSED_ARGUMENTS = “blub” # nothing expected after “OPTIONAL”
MY_INSTALL_KEYWORDS_MISSING_VALUES = “CONFIGURATIONS” # No value for “CONFIGURATIONS” given
mark_as_advanced(没用)
将CMake 的缓存变量标记为高级。
  mark_as_advanced([CLEAR|FORCE] VAR VAR2 VAR…)
  将缓存的变量标记为高级变量。其中,高级变量指的是那些在cmake GUI中,只有当“显示高级选项”被打开时才会被显示的变量。如果CLEAR是第一个选项,参数中的高级变量将变回非高级变量。如果FORCE是第一个选项,参数中的变量会被提升为高级变量。如果两者都未出现,新的变量会被标记为高级变量;如果这个变量已经是高级/非高级状态的话,它将会维持原状。
  该命令在脚本中无效。
CMake系统命令
CMake的所有的语句都写在一个叫:CMakeLists.txt的文件中。当CMakeLists.txt文件确定后,可以用ccmake命令对相关 的变量值进行配置。这个命令必须指向CMakeLists.txt所在的目录。配置完成之后,应用cmake命令生成相应的makefile(在Unix like系统下)或者 project文件(指定用window下的相应编程工具编译时)。
参数
-B
https://cmake.org/cmake/help/v3.15/manual/cmake.1.html
-B Uses as the build tree
设置编译目录,进行out-of-source(外部)编译
-H
https://cmake.org/cmake/help/v3.15/manual/cmake.1.html
with one of the following options:
–help,-help,-usage,-h,-H,/?
Print usage information and exit. 打印使用信息并退出
Usage describes the basic command line interface and its options.
-D
https://cmake.org/cmake/help/v3.15/manual/cmake.1.html
创建或修改一个cache变量
清除cmake产生的文件
cmake没有清理所有编译生成文件的clean命令
所以最好out-of-source编译,然后用rm命令删除build、install文件夹
注意
每次用CMAKE命令生成项目之前,必须删除上一次的build目录,否则其中的一些文件例如build/CMakeCache.txt仍然会带有上一次CMAKE命令的配置。

添加外部项目:ExternalProject
ExternalProject是一个模块,用于添加外部项目
使用ExternalProject模块需要先引入:
include(ExternalProject)
引入后,可以使用ExternalProject_Add,ExternalProject_Add_Step,ExternalProject_Add_StepDependencies这些核心函数。

时间戳:https://gist.github.com/taogashi/33ebf6b4285ba96419b0aea3d7f4d63e

作用
本项目可以把外部项目作为一个库来链接,即项目可以使用外部项目中的资源,而外部项目不能使用本项目的资源。
ExternalProject_Add
引入外部项目
(实测证实)配置给外部项目使用的camke命令并执行,在make时会先make外部项目,并安装外部项目生成的库到本项目中

Directory Options:
配置外部项目的目录,一般使用默认值即可。
PREFIX


外部项目的根目录。 除非下面另有说明,否则将在此处创建与外部项目关联的所有其他目录。
SOURCE_DIR
源码目录顶层,类似CMAKE_SOURCE_DIR
如果未指定上述任何… _ DIR选项,则其默认值计算如下。 如果给出PREFIX选项或设置了EP_PREFIX目录属性,则会在指定的前缀下构建并安装外部项目:
TMP_DIR = /tmp
STAMP_DIR = /src/-stamp
DOWNLOAD_DIR = /src
SOURCE_DIR = /src/
BINARY_DIR = /src/-build
INSTALL_DIR =
LOG_DIR =
未指定PREFIX,EP_PREFIX或EP_BASE,则默认设置为将PREFIX设置为名为 -prefix。 相对路径为在调用ExternalProject_Add()时的CMAKE_CURRENT_BINARY_DIR
Configure Step Options:
CMAKE_ARGS …
配置外部项目运行cmake命令时的参数。
执行本项目cmake命令时,用CMAKE_ARGS来为外部项目运行cmake命令(实测证实)
Build Step Options:
外部项目的构建选项。
BUILD_ALWAYS (不准,实测始终构建)
为1:始终构建
为0: 始终不构建

Target Options:
DEPENDS …
指定外部项目所依赖的其他目标。 在执行任何外部项目的步骤之前,其他目标将被更新。 由于外部项目在内部为每个步骤使用其他自定义目标,因此DEPENDS选项是确保所有这些步骤依赖于其他目标的最便捷方式。 简单地执行add_dependencies( )将不会使任何步骤依赖于。

ExternalProject_Get_Property
ExternalProject_Get_Property( […])
该函数将外部项目的属性值存储在同名变量中。 属性名称对应于ExternalProject_Add()的关键字参数名称(而不是cmake参数名称)。 例如,可以像这样检索源目录:
ExternalProject_Get_property(myExtProj SOURCE_DIR)#获取外部项目myExtProj的SOURCE_DIR属性
message(“Source dir of myExtProj = ${SOURCE_DIR}”)
示例

Interface Libraries:header-only libraries
https://cmake.org/cmake/help/latest/manual/cmake-buildsystem.7.html#interface-libraries
http://mariobadr.com/creating-a-header-only-library-with-cmake.html
只有头文件,没有源文件。其头文件中包含typedef、宏定义、枚举、const变量、及一些未实现的函数声明(有需要时可以自己定义并调用)

意义
Interface Libraries的意义仍然不清楚,官方文档中的用例并不能证明接口库有什么优点!!!不生成编译文件所以提高编译速度?减小生成的文件的大小?跨平台性?问一下写avpkV2的大佬吧

简化构建过程
https://stackoverflow.com/questions/12671383/benefits-of-header-only-libraries

https://softwareengineering.stackexchange.com/questions/305618/are-header-only-libraries-more-efficient

示例
eg:AVPKV2->Device Layer->interface
使用教程示例
https://elloop.github.io/tools/2016-04-05/learning-cmake-1
cmake版本问题
(3.13.5)3.15.4
find_path之前必须设置 CMAKE_INCLUDE_PATH才能找到png.h
同时make失败
CMake Error: TRY_RUN() invoked in cross-compiling mode, please set the following cache variables appropriately:
HAVE_POLL_FINE_EXITCODE (advanced)
HAVE_POLL_FINE_EXITCODE__TRYRUN_OUTPUT (advanced)
LINK_DIRECTORIES未知

3.11
find_path之前必须设置 CMAKE_INCLUDE_PATH才能找到png.h
能build成功,但是LINK_DIRECTORIES还是不行

你可能感兴趣的:(cmake,编译)