2019-07-18-cmake常用方法

仇睿
2023-12-01

layout: post
title: cmake常用方法
date: 2019-12-03 16:06:01
description: cmake常用方法
tag: cmake


1. cmake使用介绍

1.1. 概念介绍

1.1.1. directory

目录,cmake是按照目录来管理维护的
有如下属性:
COMPILE_OPTIONS :
INCLUDE_DIRECTORIES :

1.1.2. target

  • 目标,可能是一个obj,可能是一个库,可能是一个可执行文件
  • 由add_executable(), add_library(), or add_custom_target()等命令创建
  • 是编译的最小单元
  • 有如下属性:
    • COMPILE_OPTIONS :编译选项
    • COMPILE_DEFINITIONS  or /D开头,宏定义及给宏定义赋值,比如定义POSITION_INDEPENDENT_CODE等
    • DEFINE_SYMBOL :宏定义,方便导出动态库或MODULE,可以被COMPILE_DEFINITIONS代替
    • INCLUDE_DIRECTORIES :-I or -isystem开头,包含路径
    • INTERFACE_COMPILE_OPTIONS :
    • INTERFACE_COMPILE_DEFINITIONS
    • INTERFACE_INCLUDE_DIRECTORIES
    • INTERFACE_SYSTEM_INCLUDE_DIRECTORIES

1.2. 文件说明

  • cmake_install.cmake :处理安装规则的CMake脚本,在项目安装时使用。
  • CMakeCache.txt :如文件名所示,CMake缓存。CMake在重新运行配置时使用这个文件。

1.3. 内置语法

1.3.1. if

参考网址

  if(expression)
    :then section.
  elseif(expression2)
    :elseif section.
  else(expression)
    :else section.
  endif(expression)
  • elseif和else可选
  • else和endif中的expression也可选.
  • expression情况如下:
    • if(<variable|string>) 对字符串或者变量variable可以直接进行判断,变量无需使用$()
    • if(<constant>) True:1, ON, YES, TRUE, Y, 或非0. False: 0, OFF, NO, FALSE, N, IGNORE, NOTFOUND,空字符串,以OTFOUND结尾的字符串.
    • if(NOT <expression>)
    • if(<expr1> AND <expr2>)
    • if(<expr1> OR <expr2>) expre1和expr2都会被执行
    • if(COMMAND command-name) 如果command-name是可别调用的函数,命令,宏,则为TRUE,否则为FALSE
    • if(POLICY policy-id) 如果对应的policy-id设置了,则为TRUE,POLICY是cmake为了控制版本引入的类似版本控制的标识,具体详见OLICY](https://cmake.org/cmake/help/v3.0/command/cmake_policy.html?highlight=cmp nnnn)
    • if(TARGET target-name) TURE:target-name存在.其中target-name来源于add_executable(), add_library(), or d_custom_target() 命令
    • if(EXISTS path-to-file-or-directory) 文件或目录是否存在,仅支持全路径
    • if(file1 IS_NEWER_THAN file2) TURE:file1比file2新,或一样新,或都不存在.只支持全路径
    • if(IS_DIRECTORY path-to-directory) 是否是目录,只支持全路径
    • if(IS_SYMLINK file-name) 是否是符号链接,只支持全路径
    • if(IS_ABSOLUTE path) 是否是全路径
    • if(<variable|string> MATCHES regex) 变量或字符串是否正则匹配regex
    • if(<variable|string> LESS <variable|string>) 前边数字是否小于后边数字,同理还有大于(GREATER),等于(EQUAL),必须是数字
    • if(<variable|string> STRLESS <variable|string> 同上,字典比较(不限于数字),同理还有大于(STRGREATER),等于(STREQUAL)
    • if(<variable|string> VERSION_LESS <variable|string>) 前边版本是否小于后边版本号,同理还有大于(VERSION_GREATER),等VERSION_EQUAL),version format is major[.minor[.patch[.tweak]]]
    • if(DEFINED <variable>) 变量是否定义,注意宏不是变量
    • if((expression) AND (expression OR (expression))) 支持复杂混合

1.3.2. foreach/while

  • foreach endforeach 可以与break结合使用,以便尽早从循环中跳出。有四种用法:多变量,列表,Items,范围
    • foreach(loop_var arg1 arg2 …): 其中提供循环变量和显式项列表。
    • 通过指定一个范围,可以对整数进行循环,例如:foreach(loop_var range total)或foreach(loop_var range start stop [step])。
    • 对列表值变量的循环,例如:foreach(loop_var IN LISTS [list1[…]]) 。参数被解释为列表,它们的内容会自动展开。
    • 对变量的循环,例如:foreach(loop_var IN ITEMS [item1 […]])。参数的内容没有展开。
  • while-endwhile 也可以与break结合使用,以便尽早从循环中跳出。
    • 类似C语言里的while(true){}do;

1.3.3. list

  • 以分号;为分割的一个字符串,下标从0开始
  • Reading
    • list(LENGTH <list> <out-var>) 长度
    • list(GET <list> <element index> [<index> ...] <out-var>) 获取元素
    • list(JOIN <list> <glue> <out-var>) 组合后返回
    • list(SUBLIST <list> <begin> <length> <out-var>) 返回子列表
  • Search
    • list(FIND <list> <value> <out-var>) 查找值,返回索引.找不到返回-1
  • Modification
    • list(APPEND <list> [<element>...]) 后边追加
    • list(FILTER <list> {INCLUDE | EXCLUDE} REGEX <regex>)
    • list(INSERT <list> <index> [<element>...]) 指定位置插入
    • list(REMOVE_ITEM <list> <value>...) 根据内容删除
    • list(REMOVE_AT <list> <index>...) 根据索引删除
    • list(REMOVE_DUPLICATES <list>) 去重
    • list(TRANSFORM <list> <ACTION> [<SELECTOR>] [OUTPUT_VARIABLE <output variable>]) 执行指定操作,较复杂
  • Ordering
    • list(REVERSE <list>) 逆序
    • list(SORT <list>) 排序

1.3.4. string

  • 字符串操作
  • 有6类使用方法
    • Search and Replace
      • string(FIND <string> <substring> <output variable> [REVERSE])
        查找返回所有,-1表示失败.可以反向查找
      • string(REPLACE <match_string> <replace_string> <output variable> <input> [<input>...])
        用replace_string替input中出现的match_string,结果存放在variable中
    • Regular Expressions
      • string(REGEX MATCH <regular_expression> <output variable> <input> [<input>...])
      • 所有input匹配regular_expression内存查找处理啊,结果存放在variable中,匹配put会连起来作为一个input,只匹配一个结果
      • string(REGEX MATCHALL <regular_expression> <output variable> <input> [<input>...])
        同上,匹配所有结果,存放在variable列表中
      • string(REGEX REPLACE <regular_expression> <replace_expression> <output variable> <input> [<input>...])
        同上,查询结果被replace_expression替换,然后赋值给variable,注意replace_expression可以是查询的某一个,通过CMAKE_MATCH_<n> for <n> 0..9
    • Manipulation
      • string(APPEND <string-var> [<input>...]) 追加到后边,类似于+
      • string(PREPEND <string-var> [<input>...]) 追加到前边
      • string(CONCAT <out-var> [<input>...]) 连接,原来out-var会被覆盖
      • string(JOIN <glue> <out-var> [<input>...]) 使用glue连接
      • string(TOLOWER <string1> <out-var>) 变小写
      • string(TOUPPER <string1> <out-var>) 变大写
      • string(LENGTH <string> <out-var>) 取string的长度
      • string(SUBSTRING <string> <begin> <length> <out-var>) 获取子串,length为-1表示到结尾
      • string(STRIP <string> <out-var>) 去除string前后空格
      • string(GENEX_STRIP <string> <out-var>) 去除所有格的generator expressions
      • string(REPEAT <string> <count> <out-var>) string字符串拼接count次输出
    • Comparison
      • string(COMPARE <op> <string1> <string2> <out-var>) 比较字符串,返回true或false
        • op:LESS GREATER EQUAL NOTEQUAL LESS_EQUAL GREATER_EQUAL
        • 小于 大于 等于 不等于 小于等于 大于等于
    • Hashing
      • string(<HASH> <out-var> <input>) 对input字符串加密输出
        • HASH: MD5 SHA1 SHA224 … SHA3_224 SHA3_256 …
    • Generation
      • string(ASCII <number>... <out-var>) 数字转字符串
      • string(CONFIGURE <string1> <out-var> [...])
      • string(MAKE_C_IDENTIFIER <string> <out-var>) 加下划线
      • string(RANDOM [<option>...] <out-var>) 生成随记字符串
      • string(TIMESTAMP <out-var> [<format string>] [UTC]) 格式化时间
      • string(UUID <out-var> ...) 生成UUID

1.3.5. include

include(<file|module> [OPTIONAL] [RESULT_VARIABLE <VAR>] [NO_POLICY_SCOPE])

  • 导入cmake文件并且执行,如果设置了返回值,成功返回文件绝对路径,失败返回NOTFOUND
  • 包含文件或者模块,模块指后缀是.cmake的文件(modulename.cmake).
  • 优先搜索CMAKE_MODULE_PATH变量中的路径,然后再搜索CMake module directory
  • NO_POLICY_SCOPE字段可以参考cmake_policy()
  • 举例: include(3rd/cmake/helper.cmake)
  • include(3rd/cmake/helper.h)

1.3.6. 注释

注释使用#

1.4. 函数说明

1.4.1. project

project(<PROJECT-NAME> [LANGUAGES] [<language-name>...])
project(<PROJECT-NAME>
        [VERSION <major>[.<minor>[.<patch>[.<tweak>]]]]
        [LANGUAGES <language-name>...])

在最外层的CMakeLists.txt中包含,最好能设置版本号语言,默认设置为C和CXX(C++)语言

1.4.2. option

option(<option_variable> "help string describing option" [initial value])

  • 定义变量,如果给了initial value,则此参数有效.如果不给initial value,则参数无效.
  • CMAKELISTS.txt 内部定义的option,调用cmake的时候可以通过 -D<option_variable>=value 修改默认参数
  • 举例
    • OPTION(MOCK_MEGFACE “mock megface” TRUE)
    • cmake -D MOCK_MEGFACE=FALSE

1.4.3. set

set(<variable> <value> [[CACHE <type> <docstring> [FORCE]] | PARENT_SCOPE])

  • 设置一个变量,value可以有多个(多个的话,实际效果是用分号分割).CACHE(缓存)设置后对全局有效,否则只对本文件有效.
  • 举例set(EP_MIRROR_DIR “http://10.201.102.223:8111/sources” CACHE STRING “mirrors th”)
  • 通过${EP_MIRROR_DIR}来获取变量内容
  • 参数type:
    • FILEPATH = File chooser dialog.
    • PATH = Directory chooser dialog.
    • STRING = Arbitrary string.
    • BOOL = Boolean ON/OFF checkbox.
    • INTERNAL = No GUI entry (used for persistent variables).
    • PARENT_SCOPE: value的范围

1.4.4. unset

unset(<variable> [CACHE | PARENT_SCOPE])

  • 清除变量内容
  • CACHE:全局有效
  • PARENT_SCOPE: 改变变量范围

1.4.5. add_custom_target

添加一个目标,它没有输出;这样它就总是会被构建。
add_custom_target(Name [ALL] [command1 [args1…]]
[COMMAND command2 [args2…] …]
[DEPENDS depend depend depend … ]
[BYPRODUCTS [files…]]
[WORKING_DIRECTORY dir]
[COMMENT comment]
[JOB_POOL job_pool]
[VERBATIM] [USES_TERMINAL]
[COMMAND_EXPAND_LISTS]
[SOURCES src1 [src2…]])
添加具有给定名称的目标,以执行给定命令。目标没有输出文件, 即使命令尝试使用目标名称创建文件,也始终将其视为已过期。使用add_custom_command()命令生成具有依赖性的文件。默认情况下,任何内容都不取决于自定义目标。使用add_dependencies() 命令添加与其他目标之间的依赖关系。

举例:将目录 C M A K E C U R R E N T L I S T D I R / d a t a 拷 贝 到 {CMAKE_CURRENT_LIST_DIR}/data拷贝到 CMAKECURRENTLISTDIR/data{BIN_DIR}/data
add_custom_target(
copyData ALL
COMMAND cmake -E copy_directory
${CMAKE_CURRENT_LIST_DIR}/data ${BIN_DIR}/data
)

1.4.6. add_library

  1. add_library(<name> [STATIC | SHARED | MODULE] [EXCLUDE_FROM_ALL] source1 [source...])
    普通的库编译,可以编译动态库,静态库以及模块.
  2. add_library(<name> <SHARED|STATIC|MODULE|UNKNOWN> IMPORTED [GLOBAL])
    导入已经编译好的库
  3. add_library(<name> OBJECT <src>...)
    定义个obj变量,此变量可以被 add_library 或 add_executable 通过 $<TARGET_OBJECTS:objlib 调用,其中objlib就是name,或者被 target_link_libraries 链接,比如即生成动态库,有生成静态库。可以先生成obj,然后再分别生成来解决同名问题。
  4. add_library(<name> ALIAS <target>)
    顾名思义,这种库为项目中已存在的库目标定义别名。不过,不能为 IMPORTED 库定义别名。
  5. add_library(<name> INTERFACE [IMPORTED [GLOBAL]])
    创建一个接口库,和方法3有点类似.这种库与IMPORTED库类似,不过,该类型库可变,没有位置信息。它主要用于项目之外的目标建模使用。

1.4.7. add_executable

  1. add_executable(<name> [WIN32] [MACOSX_BUNDLE] [EXCLUDE_FROM_ALL] [source1] urce2 ...])
    编译一个普通target,name必须全局唯一,name后边是否有后缀(比如.exe)取决于本地环境,写的时加后缀.
    可以通过修改 RUNTIME_OUTPUT_DIRECTORY 改变生成目录,通过 OUTPUT_NAME 修改 name
    [WIN32]MFC使用, [MACOSX_BUNDLE]IOS系统使用, [EXCLUDE_FROM_ALL]默认
    set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ./exercise/) 必须在add_executable之前定义有效
  2. add_executable(<name> IMPORTED [GLOBAL])
    待细化
  3. add_executable(<name> ALIAS <target>)
    给target定义一个别名,别名的使用有限制,需要注意

1.4.8. add_compile_options

add_compile_options(<option> ...)

  • 说明:添加编译选项,待细化
  • 举例:
  • add_compile_options(-Wno-deprecated-declarations)
  • add_compile_options(/utf-8 /wd4800 /wd4819 /wd4101 /std:c++14)
  • add_compile_options($< $<COMPILE_LANGUAGE:CXX>:/utf-8>)
  • dd_compile_options($< $<COMPILE_LANGUAGE:CXX>:/wd4819>)

1.4.9. add_subdirectory

add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL])

  • source_dir可以是相对路径,可以是绝对路径
  • binary_dir指定编译生成路径,如果不设置默认等于source_dir
  • EXCLUDE_FROM_ALL被指定的话,所有的子目录targe不会被包含到父目录(并且也不会被IDE包含).一般子目录有些内容不被父目录使用的话,可以指定.设置此参数后,子目录必须显示的build targe

1.4.10. include_directories

include_directories([AFTER|BEFORE] [SYSTEM] dir1 [dir2 ...])

  • 添加依赖路径,可以是相对路径,可以是据对路径.
  • 路径被添加到文件变量INCLUDE_DIRECTORIES中,可以被本文件搜索
  • AFTER和BEFORE可以确定是插到变量的前边还是后边.
  • SYSTEM可以表示此目录和系统有关,具体参考编译器文档.

1.4.11. target_sources

target_sources(<target> <INTERFACE|PUBLIC|PRIVATE> [items1...] [<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])

  • 相关概念参考
  • 给target指定源文件,target必须由add_executable() or add_library()创建,并且不可以是别名
  • INTERFACE, PUBLIC and PRIVATE指示后边跟着参数的范围
  • PRIVATE and PUBLIC定义的item属于target的SOURCES性质
  • PUBLIC and INTERFACE定义的item属于target的INTERFACE_SOURCES性质
  • Imported Targets仅支持INTERFACE标签

1.4.12. target_compile_definitions

target_compile_definitions(<target> <INTERFACE|PUBLIC|PRIVATE> [items1...] [<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])

  • 增加编译选项, COMPILE_DEFINITIONS 中的条目添加-D或/D前缀后出现在编译命令行中,顺序不定。
  • PRIVATE and PUBLIC属于target的COMPILE_DEFINITIONS
  • PUBLIC and INTERFACE属于target的INTERFACE_COMPILE_DEFINITIONS
  • IMPORTED targets only support INTERFACE items
  • 举例: -D及空格会被忽略,下边例子效果一样
    • target_compile_definitions(foo PUBLIC FOO)
    • target_compile_definitions(foo PUBLIC -DFOO) # -D removed
    • target_compile_definitions(foo PUBLIC “” FOO) # “” ignored
    • target_compile_definitions(foo PUBLIC -D FOO) # -D becomes “”, then ignored

add_definitions(-DIS_LINUX) 项目级别的defintions

1.4.13. target_include_directories

target_include_directories(<target> [SYSTEM] [BEFORE]
  <INTERFACE|PUBLIC|PRIVATE> [items1...]
  [<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])
  • 给target添加依赖路径,可以是相对路径,可以是据对路径.target必须由add_executable() add_library()创建,并且不可以是别名
  • INTERFACE 供父目录使用,PUBLIC本文件和父目录都可使用,PRIVATE仅供本目录使用
  • BEFORE : 属性会追加到前边,否则append到其他参数后边
  • PRIVATE and PUBLIC属于target的INCLUDE_DIRECTORIES
  • PUBLIC and INTERFACE属于target的INTERFACE_INCLUDE_DIRECTORIES
  • SYSTEM and (PUBLIC or INTERFACE)属于target的INTERFACE_SYSTEM_INCLUDE_DIRECTORIES
  • IMPORTED targets only support INTERFACE items
  • 举例:target_include_directories(mylib PUBLIC $<BUILD_INTERFACE{CMAKE_CURRENT_SOURCE_DIR}/include/mylib> $<INSTALL_INTERFACE:include/mylib:<prefix>/include/mylib)

1.4.14. target_compile_options

target_compile_options(<target> [BEFORE]
  <INTERFACE|PUBLIC|PRIVATE> [items1...]
  [<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])
  • 添加编译选项和 target_compile_definitions 类似,COMPILE_OPTIONS 中的条目原样出现在编译命令行中,而definition会加-D出现
  • BEFORE : 确定是插到变量的前边还是后边.
  • PRIVATE and PUBLIC 属于 target 的 COMPILE_OPTIONS
  • PUBLIC and INTERFACE 属于 target 的 INTERFACE_COMPILE_OPTIONS
  • cmake --build . – VERBOSE=1可以查看编译器选项

1.4.15. target_link_libraries

target_link_libraries(<target> ... <item>... ...)

  • 相关概念参考
  • 执行链接操作,可以链接生成库,也可以链接生成可执行文件,通过 add_library 或 add_executable 之后,必须调用 target_link_libraries 来完成链接
  • target 必须由 add_executable() or add_library() 创建,并且不可以是别名,并且是当前目录创建的
  • item 可能是下边中的一种:target库,全路径的库文件,不包含路径的库(会从系统目录搜索),link-flag,<debug, optimized, general>
  • 静态库支持循环嵌套
  • 有多种使用方法,具体参考
  1. target_link_libraries(<target> <PRIVATE|PUBLIC|INTERFACE> <item>... [<PRIVATE|PUBLIC|INTERFACE> <item>...]...)
    PRIVATE:仅仅编译到target中,不对外提供接口
    PUBLIC:编译到target中,同时对外提供接口
    INTERFACE:不编译到target中,仅仅对外提供其接口
  2. target_link_libraries(<target> <item>...)
    上边的特例,相当于PUBLIC
  3. target_link_libraries(<target> <LINK_PRIVATE|LINK_PUBLIC> <lib>... [<LINK_PRIVATE|LINK_PUBLIC> <lib>...]...)
    仅为了兼容,可以不使用
  4. target_link_libraries(<target> LINK_INTERFACE_LIBRARIES <item>...)
    仅为了兼容,可以不使用

1.4.16. target_link_options

target_link_options(<target> [BEFORE]
  <INTERFACE|PUBLIC|PRIVATE> [items1...]
  [<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])

Add options to the link step for an executable, shared library or module library target.
将选项添加到可执行文件,共享库或模块库目标,此命令不能用于为静态库目标添加选项。

1.4.17. set_target_properties

set_target_properties(target1 target2 ...
                      PROPERTIES prop1 value1
                      prop2 value2 ...)

设置target属性,map结构
举例如下

  • 设置标准
    • CXX_STANDARD会设置我们想要的标准。
    • CXX_EXTENSIONS告诉CMake,只启用ISO C++标准的编译器标志,而不使用特定编译器的扩展。
    • CXX_STANDARD_REQUIRED必需指定所选标准的版本。如果这个版本不可用,CMake将停止配置并出现错误。当这个属性被设置为OFF时,CMake将寻找下一个标准的最新版本,直到一个合适的标志。这意味着,首先查找C++14,然后是C++11,然后是C++98。(译者注:目前会从C++20或C++17开始查找)
    set_target_properties(animal-farm
    PROPERTIES
        CXX_STANDARD 14
        CXX_EXTENSIONS OFF
        CXX_STANDARD_REQUIRED ON
    )

1.4.18. add_dependencies

add_dependencies(<target> [<target-dependency>]...)

Add a dependency between top-level targets.
Makes a top-level <target> depend on other top-level targets to ensure that they build before <target> does. A top-level target is one created by one of the add_executable(), add_library(), or add_custom_target() commands

1.4.19. configure_file

configure_file(<input> <output>
               [COPYONLY] [ESCAPE_QUOTES] [@ONLY]
               [NEWLINE_STYLE [UNIX|DOS|WIN32|LF|CRLF] ])
  • 将input文件拷贝到output文件中
  • 拷贝过程中使用当前cmakefile中的变量,替换input文件中@VAR@ 或 ${VAR}标识的参数.比如:
    • input有如下代码:test: “@FOO_STRING@”
    • 调用的时候set(FOO_STRING “foo”)
    • 则实际拷贝后的内容为test “foo”
if(FOO_ENABLE)
  set(FOO_STRING "foo")
endif()
configure_file(foo.h.in foo.h @ONLY)

1.4.20. math

math(EXPR <variable> "<expression>" [OUTPUT_FORMAT <format>])

  • 计算表达式expression,将结果赋值给variable。expression必须使用双引号包起来
  • format: DECIMAL或HEXADECIMAL,默认是10进制
  • 举例:
    • math(EXPR value “100 * 0xA” OUTPUT_FORMAT DECIMAL) # value is set to “1000”
    • math(EXPR value “100 * 0xA” OUTPUT_FORMAT HEXADECIMAL) # value is set to “0x3e8”

1.4.21. ExternalProject

  • External Project Definition
    • ExternalProject_Add(<name> [<option>...])
      • 添加外部工程执行
      • name:外部工程名字
      • option: 参数很多,常用如下:
        • EXCLUDE_FROM_ALL: 排除外部工程构建。When enabled, this option excludes the external project from the default ALL target of the main build.
        • INSTALL_DIR: 程序安装目录
        • SOURCE_DIR: 源码存放目录
        • DEPENDS: 依赖project
        • URL: 下载代码地址,可以是http,可以是本地…
        • DOWNLOAD_NAME: 下载下来后的名称,一般很少有
        • DOWNLOAD_DIR: URL下载到本地的目录
        • DOWNLOAD_NO_PROGRESS: 不显示下载进度,默认为FALSE,显示进度
        • PATCH_COMMAND: 指定一个自定义命令,用于在更新后对源代码进行补丁。
        • CMAKE_ARGS: 传递给cmake的参数
        • LOG_BUILD: 是否输出编译日志
        • CONFIGURE_COMMAND: configure命令信息 --prefix=<INSTALL_DIR>
        • BUILD_COMMAND: 编译命令
        • BUILD_BYPRODUCTS: 指定由 BUILD_COMMAND 生成的文件名称
  • Obtaining Project Properties
    • ExternalProject_Get_Property(<name> <prop1> [<prop2>...])
      • 获取外部工程属性
      • 举例:
        • ExternalProject_Get_property(myExtProj SOURCE_DIR)
        • message(“Source dir of myExtProj = ${SOURCE_DIR}”)
  • Explicit Step Management 管理外部依赖及步骤顺序
    • ExternalProject_Add_Step(<name> <step> [<option>...])
    • ExternalProject_Add_StepTargets(<name> [NO_DEPENDS] <step1> [<step2>...])
    • ExternalProject_Add_StepDependencies(<name> <step> <target1> [<target2>...])
  • Examples

1.4.22. 各种宏定义

  • cmake --system-information output.txt 所有可以通过-D设置的参数,输出到output.txt中

1.4.22.1. 工程属性

  • PROJECT_NAME: 工程名称,通过函数project()设置
  • PROJECT_SOURCE_DIR, <PROJECT-NAME>_SOURCE_DIR 源码目录
  • PROJECT_BINARY_DIR, <PROJECT-NAME>_BINARY_DIR 二进制目录
  • PROJECT_VERSION, <PROJECT-NAME>_VERSION , 版本号,默认为空
  • PROJECT_VERSION_MAJOR, <PROJECT-NAME>_VERSION_MAJOR
  • PROJECT_VERSION_MINOR, <PROJECT-NAME>_VERSION_MINOR
  • PROJECT_VERSION_PATCH, <PROJECT-NAME>_VERSION_PATCH
  • PROJECT_VERSION_TWEAK, <PROJECT-NAME>_VERSION_TWEAK

1.4.22.2. 语言属性

  • 其中<LANG>是受支持的任何一种语言,比如C/CXX/Fortran等
  • CMAKE_<LANG>_COMPILER: 某种语言的编译器
  • CMAKE_<LANG>_COMPILER_LOADED:如果为项目启用了语言<LANG>,则将设置为TRUE或"1"。
  • CMAKE_<LANG>_COMPILER_ID:编译器标识字符串,编译器供应商所特有。注意,不能保证为所有编译器或语言定义此变量。举例如下:
    • Absoft = Absoft Fortran (absoft.com)
    • ADSP = Analog VisualDSP++ (analog.com)
    • AppleClang = Apple Clang (apple.com)
    • Clang = LLVM Clang (clang.llvm.org)
    • Cray = Cray Compiler (cray.com)
    • Embarcadero, Borland = Embarcadero (embarcadero.com)
    • G95 = G95 Fortran (g95.org)
    • GNU = GNU Compiler Collection (gcc.gnu.org)
    • HP = Hewlett-Packard Compiler (hp.com)
    • Intel = Intel Compiler (intel.com)
    • MIPSpro = SGI MIPSpro (sgi.com)
    • MSVC = Microsoft Visual Studio (microsoft.com)
    • PGI = The Portland Group (pgroup.com)
    • PathScale = PathScale (pathscale.com)
    • SDCC = Small Device C Compiler (sdcc.sourceforge.net)
    • SunPro = Oracle Solaris Studio (oracle.com)
    • TI = Texas Instruments (ti.com)
    • TinyCC = Tiny C Compiler (tinycc.org)
    • Watcom = Open Watcom (openwatcom.org)
    • XL, VisualAge, zOS = IBM XL (ibm.com)
  • CMAKE_<LANG>_STANDARD: 要求版本号
  • CMAKE_COMPILER_IS_GNU<LANG>:如果语言<LANG>是GNU编译器集合的一部分,则将此逻辑变量设置为TRUE。C语言为CC, C++语言为CXX, Fortran语言为G77。
  • CMAKE_<LANG>_COMPILER_VERSION:此变量包含一个字符串,该字符串给定语言的编译器版本。版本信息在major[.minor[.patch[.tweak]]]中给出。

1.4.22.3. target属性

  • INCLUDE_DIRECTORIES:include包含路径,详见include_directories()函数
  • COMPILE_DEFINITIONS:
  • COMPILE_OPTIONS:编译选项
  • DEFINE_SYMBOL: 宏定义,类似于#define,一般到处动态库的时候,用来作导入dllimport还是导出dllexport的判断

1.4.22.4. 程序属性

  • OUTPUT_NAME: 最终target的名称,
  • POSITION_INDEPENDENT_CODE: Whether to create a position-independent target,This property is initialized bythe value of the CMAKE_POSITION_INDEPENDENT_CODE variable

1.4.22.5. 构建类型

  • CMAKE_BUILD_TYPE : 该变量默认为空,CMake识别的值为
    • Debug:用于在没有优化的情况下,使用带有调试符号构建库或可执行文件。
    • Release:用于构建的优化的库或可执行文件,不包含调试符号。
    • RelWithDebInfo:用于构建较少的优化库或可执行文件,包含调试符号。
    • MinSizeRel:用于不增加目标代码大小的优化方式,来构建库或可执行文件。
    • 举例
      • cmake … -G"Visual Studio 12 2017 Win64" -D CMAKE_CONFIGURATION_TYPES=“Release;Debug” //将为Release和Debug配置生成一个构建树。
      • cmake --build . --config Release //通过config指定具体编译类型
  • BUILD_SHARED_LIBS : 构建动态库,默认是ON

1.4.22.6. 公共属性

  • CMAKE_CURRENT_SOURCE_DIR:当前目录
  • CMAKE_CURRENT_BINARY_DIR:当前target目录
  • CMAKE_CURRENT_LIST_DIR:当前正在处理的listfile的完整目录.
  • CMAKE_VERBOSE_MAKEFILE: 是否记录catch数据,方便再次编译时不用从头开始.一般记录在CMakeCache.txt中
  • CMAKE_MODULE_PATH: 被 include() or find_package() 命令有限搜索的以;分割的list路径列表,默认是空,由用户通过set()设置
  • CMAKE_INCLUDE_CURRENT_DIR :默认为OFF,如果开启, CMAKE_CURRENT_SOURCE_DIR and CMAKE_CURRENT_BINARY_DIR 自动添加对应directory的INCLUDE_DIRECTORIES中.不会自动传递给子目录.适合于源外构建
  • CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE: 默认为OFF,如果开启,shared library target, static library target,module target and executable target的CMAKE_CURRENT_SOURCE_DIR and CMAKE_CURRENT_BINARY_DIR自动添加到对应targetINTERFACE_INCLUDE_DIRECTORIES中.

1.4.22.7. 操作系统及系统相关预定义

  • CMAKE_SYSTEM_NAME:Linux/Darwin/Windows,在具有uname命令的系统上,将此变量设置为uname -s的输出。该变量在macOS上设置为“Darwin”。在Linux和Windows上,它分别计算为“Linux”和“Windows”。
  • CMAKE_HOST_SYSTEM_PROCESSOR:“i386”、“i686”、“x86_64”、“AMD64”
  • CMAKE_SIZEOF_VOID_P:为void指针的大小8或4,使用CMAKE_SIZEOF_VOID_P是检查当前CPU是否具有32位或64位架构的唯一“真正”可移植的方法。
  • 检测处理器指令集:NUMBER_OF_LOGICAL_CORES/NUMBER_OF_PHYSICAL_CORES/TOTAL_VIRTUAL_MEMORY/AVAILABLE_VIRTUAL_MEMORY/TOTAL_PHYSICAL_MEMORY/AVAILABLE_PHYSICAL_MEMORY/IS_64BIT/HAS_FPU/HAS_MMX/HAS_MMX_PLUS/HAS_SSE/HAS_SSE2/HAS_SSE_FP/HAS_SSE_MMX/HAS_AMD_3DNOW/HAS_AMD_3DNOW_PLUS/HAS_IA64/OS_NAME/OS_RELEASE/OS_VERSION/OS_PLATFORM…

1.4.23. cmake_parse_arguments

//可用于函数或宏
cmake_parse_arguments(<prefix> <options> <one_value_keywords>
                      <multi_value_keywords> args...)

//只用于函数
cmake_parse_arguments(PARSE_ARGV N <prefix> <options> <one_value_keywords>
                      <multi_value_keywords>)

在函数或宏中使用,用于解析输入参数。参数解析后定了一些变量,存放参数指定的选项。
<options>包含不需要后接值的选项。
<one_value_keywords>包含只可后接一个值的选项。
<multi_value_keywords>包含可后接多个值的多项。
cmake_parse_arguments将会定义一系列变量,名称为<prefix>_keyword,变量存储了从参数列表中解析到的值,对于<options>变量的值是TRUE或FALSE。
所有未解析到的参数被收集到<prefix>_UNPARSED_ARGUMENTS中。
举例如下:

function(MY_INSTALL)
    set(options OPTIONAL FAST)
    set(oneValueArgs DESTINATION RENAME)
    set(multiValueArgs TARGETS CONFIGURATIONS)
    cmake_parse_arguments(MY_INSTALL "${options}" "${oneValueArgs}"
                          "${multiValueArgs}" ${ARGN} )
endfunction(MY_INSTALL)

my_install(TARGETS foo bar DESTINATION bin OPTIONAL blub)

//结果如下:
// 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")

1.5. 参考资料

  1. learning-cmake
  2. cmake-cookbook
  3. cmake实践
  4. CMake Cookbook
 类似资料: