CMD#65: separate_arguments
将空格分隔的参数解析为一个分号分隔的list。
separate_arguments(<var> <UNIX|WINDOWS>_COMMAND "<args>")
解析一个unix或者windows风格的命令行字符串"<args>",并将结果以分号分隔的list的形式存储到<var>中。整个命令行都必须从这个"<args>"参数中给出。
UNIX_COMMAND模式以没有被括起来的白字符为参数的分隔符。它可以识别单引号和双引号的引号对。反斜杠可以对下一个字符的字面值转义(\",就是");没有其他特殊的转义字符(例如\n就是n)。
WINDOWS_COMMAND模式按照与运行时库相同的语法解析一个windows命令行,在启动(starrtup)时构造argv。它使用没有被双引号括起来的白字符来分隔参数。反斜杠维持其字面含义,除非它们在双引号之前。更多细节,参见MSDN的文章:"Parsing C Command-Line Arguments"。
separate_arguments(VARIABLE)
将VARIABLE的值转换为一个分号分隔的list。所有的空格会被替换为';'。该命令可以用来辅助生成命令行。
CMD#66: set
将一个CMAKE变量设置为给定值。
set(<variable> <value> [[CACHE <type> <docstring> [FORCE]] | PARENT_SCOPE])
将变量<variable>的值设置为<value>。在<variable>被设置之前,<value>会被展开。如果有CACHE选项,那么<variable>就会添加到cache中;这时<type>和<docstring>是必需的。<type>被CMake GUI用来选择一个窗口,让用户设置值。<type>可以是下述值中的一个:
FILEPATH = 文件选择对话框。
PATH = 路径选择对话框。
STRING = 任意的字符串。
BOOL = 布尔值选择复选框。
INTERNAL = 不需要GUI输入端。(适用于永久保存的变量)。
如果<type>是内部的(INTERNAL),那么<value>总是会被写入到cache中,并替换任何已经存在于cache中的值。如果它不是一个cache变量,那么这个变量总是会写入到当前的makefile中。FORCE选项将覆盖cache值,从而去掉任何用户带来的改变。
如果指定了PARENT_SCOPE选项,变量<variable>将会被设置为当前作用域之上的作用域中。每一个新的路径或者函数都可以创建一个新作用域。该命令将会把一个变量的值设置到父路径或者调用函数中(或者任何类似的可用的情形中。)
如果没有指定<value>,那么这个变量就会被撤销而不是被设置。另见:unset()命令。
set(<variable> <value1> ... <valueN>)
在这种情形下,<variable>被设置为一个各个值之间由分号分隔的list。
<variable>可以是环境变量,比如:
set( ENV{PATH} /home/martink )
在这种情形下,环境变量将会被设置。
CMD#67: set_directory_properties
设置某个路径的一种属性。
set_directory_properties(PROPERTIES prop1 value1 prop2 value2)
为当前的路径及其子路径设置一种属性。如果该属性不存在,CMake将会报告一个错误。属性包括:INCLUDE_DIRECTORIES, LINK_DIRECTORIES, INCLUDE_REGULAR_EXPRESSION, 以及ADDITIONAL_MAKE_CLEAN_FILES共四种。ADDITIONAL_MAKE_CLEAN_FILES是一个文件名的list,其中包含有"make clean"阶段会被清除掉的文件。
CMD#68: set_property
在给定的作用域内设置一个命名的属性。
set_property(<GLOBAL |
DIRECTORY [dir] |
TARGET [target1 [target2 ...]] |
SOURCE [src1 [src2 ...]] |
TEST [test1 [test2 ...]] |
CACHE [entry1 [entry2 ...]]>
[APPEND]
PROPERTY <name> [value1 [value2 ...]])
为作用域里的0个或多个对象设置一种属性。第一个参数决定了属性可以影响到的作用域。他必须是下述值之一:GLOBAL,全局作用域,唯一,并且不接受名字。DIRECTORY,路径作用域,默认为当前路径,但是也可以用全路径或相对路径指定其他值。TARGET,目标作用域,可以命名0个或多个已有的目标。SOURCE,源作用域,可以命名0个或多个源文件。注意,源文件属性只对加到相同路径(CMakeLists.txt)中的目标是可见的。TEST 测试作用域可以命名0个或多个已有的测试。CACHE作用域必须指定0个或多个cache中已有的条目。
PROPERTY选项是必须的,并且要紧跟在待设置的属性的后面。剩余的参数用来组成属性值,该属性值是一个以分号分隔的list。如果指定了APPEND选项,该list将会附加在已有的属性值之后。
CMD#69: set_source_files_properties
源文件有一些属性来可以改变它们构建的方式。
set_source_files_properties([file1 [file2 [...]]]
PROPERTIES prop1 value1
[prop2 value2 [...]])
以键/值对的方式设置与源文件相关的那些属性值。那些CMake中的源文件属性,参见关于属性的相关文档。不能被识别的属性将会被忽略。源文件属性只对同一路径(CMakeLists.txt)中添加的目标可见。
CMD#70: set_target_properties
设置目标的一些属性来改变它们构建的方式。
set_target_properties(target1 target2 ...
PROPERTIES prop1 value1
prop2 value2 ...)
为一个目标设置属性。该命令的语法是列出所有你想要变更的文件,然后提供你想要设置的值。你能够使用任何你想要的属性/值对,并且在随后的代码中调用GET_TARGET_PROPERTY命令取出属性的值。
影响一个目标输出文件的名字的属性详述如下。PREFIX和SUFFIX属性覆盖了默认的目标名前缀(比如lib)和后缀(比如.so)。IMPORT_PREFIX和IMPORT_SUFFIX是与之等价的属性,不过针对的是DLL(共享库目标)的导入库。在构建目标时,OUTPUT_NAME属性设置目标的真实名字,并且可以用来辅助创建两个具有相同名字的目标,即使CMake需要唯一的逻辑目标名。<CONFIG>_OUTPUT_NAME可以为不同的配置设置输出的目标名字。当目标在指定的配置名<CONFIG>(全部大写,例如DEBUG_POSTFIX)下被构建时,<CONFIG>_POSTFIX为目标的真实名字设置一个后缀。该属性的值在目标创建时被初始化为CMAKE_<CONFIG>_POSTFIX的值(可执行目标除外,因为较早的CMake版本不会为可执行文件使用这个属性。)
LINK_FLAGS属性可以用来为一个目标的链接阶段添加额外的标志。LINK_FLAGS_<CONFIG>将为配置<CONFIG>添加链接标志,例如DEBUG,RELEASE,MINSIZEREL,RELWITHDEBINFO。DEFINE_SYMBOL属性设置了编译一个共享库中的源文件时才会被定义的预处理器符号名。如果这个值没有被设置的话,那么它会被设置为默认值target_EXPORTS(如果目标不是一个合法的C标示符的话可以用一些替代标志)。这对于检测头文件是包含在它们的库以内还是以外很有帮助,从而可以合理设置dllexport/dllimport修饰符(注意,只有在编译到的时候,这个符号才会被定义;因此猜测在代码中,判断预处理符号是否被定义可以知道依赖库是导入的还是导出的——译注)。COMPILE_FLAGS属性可以设置附加的编译器标志,它们会在构建目标内的源文件时被用到。它也可以用来传递附加的预处理器定义。
LINKER_LANGUAGE属性用来改变链接可执行文件或共享库的工具。默认的值是设置与库中的文件相匹配的语言。CXX和C是这个属性的公共值。
对于共享库,VERSION和SOVERSION属性分别可以用来指定构建的版本号以及API版本号。当构建或者安装时,如果平台支持符号链接并且链接器支持so名字,那么恰当的符号链接会被创建。如果只指定两者中的一个,缺失的另一个假定为具有相同的版本号。对于可执行文件,VERSION可以被用来指定构建版本号。当构建或者安装时,如果该平台支持符号链接,那么合适的符号链接会被创建。对于在Windows系统而言,共享库和可执行文件的VERSION属性被解析成为一个"major.minor"的版本号。这些版本号被用做该二进制文件的镜像版本。
还有一些属性用来指定RPATH规则。INSTALL_RPATH是一个分号分隔的list,它指定了在安装目标时使用的rpath(针对支持rpath的平台而言)(-rpath在gcc中用于在编译时指定加载动态库的路径;优先级较系统库路径要高。详情参见http://www.cmake.org/Wiki/CMake_RPATH_handling#What_is_RPATH_.3F——译注)。INSTALL_RPATH_USE_LINK_PATH是一个布尔值属性,如果它被设置为真,那么在链接器的搜索路径中以及工程之外的目录会被附加到INSTALL_RPATH之后。SKIP_BUILD_RPATH是一个布尔值属性,它指定了是否跳过一个rpath的自动生成过程,从而可以从构建树开始运行。BUILD_WITH_INSTALL_RPATH是一个布尔值属性,它指定了是否将在构建树上的目标与INSTALL_RPATH链接。该属性要优先于SKIP_BUILD_RPATH,因此避免了安装之前的重新链接。INSTALL_NAME_DIR是一个字符串属性,它用于在Mac OSX系统上,指定了被安装的目标中使用的共享库的"install_name"域的目录部分。如果目标已经被创建,变量CMAKE_INSTALL_RPATH, CMAKE_INSTALL_RPATH_USE_LINK_PATH, CMAKE_SKIP_BUILD_RPATH, CMAKE_BUILD_WITH_INSTALL_RPATH和CMAKE_INSTALL_NAME_DIR的值会被用来初始化这个属性。
PROJECT_LABEL属性可以用来在IDE环境,比如visual studio,中改变目标的名字。 VS_KEYWORD可以用来改变visual studio的关键字,例如如果该选项被设置为Qt4VSv1.0的话,QT集成将会运行得更好。
VS_SCC_PROJECTNAME, VS_SCC_LOCALPATH, VS_SCC_PROVIDER可以被设置,从而增加在一个VS工程文件中对源码控制绑定的支持。
PRE_INSTALL_SCRIPT和POST_INSTALL_SCRIPT属性是在安装一个目标之前及之后指定运行CMake脚本的旧格式。只有当使用旧式的INSTALL_TARGETS来安装目标时,才能使用这两个属性。使用INSTALL命令代替这种用法。
EXCLUDE_FROM_DEFAULT_BUILD属性被visual studio生成器使用。如果属性值设置为1,那么当你选择"构建解决方案"时,目标将不会成为默认构建的一部分。
CMD#71: set_tests_properties
设置若干个测试的属性值。
set_tests_properties(test1 [test2...] PROPERTIES prop1 value1 prop2 value2)
为若干个测试设置一组属性。若属性未被发现,CMake将会报告一个错误。这组属性包括:WILL_FAIL, 如果设置它为true,那将会把这个测试的“通过测试/测试失败”标志反转。PASS_REGULAR_EXPRESSION,如果它被设置,这个测试的输出将会被检测是否违背指定的正则表达式,并且至少要有一个正则表达式要匹配;否则测试将会失败。
例子: PASS_REGULAR_EXPRESSION "TestPassed;All ok"
FAIL_REGULAR_EXPRESSION: 如果该属性被设置,那么只要输出匹配给定的正则表达式中的一个,那么测试失败。
例子: PASS_REGULAR_EXPRESSION "[^a-z]Error;ERROR;Failed"
PASS_REGULAR_EXPRESSION和FAIL_REGULAR_EXPRESSION属性都期望一个正则表达式列表(list)作为其参数。
TIMEOUT: 设置该属性将会限制测试的运行时长不超过指定的秒数。
CMD#72: site_name
将给定的变量设定为计算机名。
site_name(variable)
为Makefile中的源文件定义一个分组。CMD#73:
source_group
source_group(name [REGULAR_EXPRESSION regex] [FILES src1 src2 ...])
为工程中的源文件中定义一个分组。这主要用来在Visual Studio中建立文件组按钮(file tabs)。所有列出来的文件或者匹配正则表达式的文件都会被放到这个文件组中。如果一个文件匹配多个组,那么最后明确地列出这个文件的组将会包含这个文件,如果有这样的组的话。如果没有任何组明确地列出这个文件,那么最后那个其正则表达式与该文件名匹配的组,将会成为最终候选者。
组名中可以包含反斜杠,以指定子文件组:source_group(outer\\inner ...)
为了保持后向兼容性,这个命令也支持这种格式:source_group(name regex)
CMD#74: string
字符串操作函数。
string(REGEX MATCH <regular_expression> <output variable> <input> [<input>...])
string(REGEX MATCHALL <regular_expression> <output variable> <input> [<input>...])
string(REGEX REPLACE <regular_expression> <replace_expression> <output variable> <input> [<input>...])
string(REPLACE <match_string> <replace_string> <output variable> <input> [<input>...])
string(COMPARE EQUAL <string1> <string2> <output variable>)
string(COMPARE NOTEQUAL <string1> <string2> <output variable>)
string(COMPARE LESS <string1> <string2> <output variable>)
string(COMPARE GREATER <string1> <string2> <output variable>)
string(ASCII <number> [<number> ...] <output variable>)
string(CONFIGURE <string1> <output variable> [@ONLY] [ESCAPE_QUOTES])
string(TOUPPER <string1> <output variable>)
string(TOLOWER <string1> <output variable>)
string(LENGTH <string> <output variable>)
string(SUBSTRING <string> <begin> <length> <output variable>)
string(STRIP <string> <output variable>)
string(RANDOM [LENGTH <length>] [ALPHABET <alphabet>] [RANDOM_SEED <seed>] <output variable>)
REGEX MATCH : 匹配正则表达式一次,然后将匹配的值存储到输出变量中。
REGEX MATCHALL : 尽可能多次地匹配正则表达式,然后将匹配的值以list的形势存储到输出变量中。
REGEX REPLACE : 尽可能多次地匹配正则表达式,并且将匹配的值用replacement expression 替换掉,然后存储到输出变量中。这个replace expression 可以引用包含匹配字符串的子表达式,这些匹配的字符串用圆括号隔开的\1,\2,...,\9等加以引用。注意:在CMake代码里,如果要使用一个反斜杠,必须要用两个反斜杠(\\1)转义,才能通过参数解析。
REPLACE : 将输入字符串内所有出现match_string的地方都用replace_string代替,然后将结果存储到输出变量中。
COMPARE EQUAL/NOTEQUAL/LESS/GREATER : 将会比较两个字符串,然后将比较的结果(true/false)存储到输出变量中。
ASCII : 将会把所有数字转换为对应的ASCII字符。
CONFIGURE : 将一个字符串进行变换,这种变换与将一个FILE变换为CONFIGURE_FILE相似。
TOUPPER/TOLOWER : 将字符串转换为大写/小写字符。
LENGTH : 返回给定字符串的长度。
SUBSTRING : 返回给定字符串的子串。
STRIP : 返回一个给定字符串的子串,它会去掉原先字符串开始和结尾的空格。
RANDOM : 将会返回一个给定长度的随机字符串,它由给定的字母表中的字母组成。默认的长度是5个字符,默认的字母表是全部的大小写字母以及数字。如果指定了一个整数RANDOM_SEED,它的值将会被用做随机数发生器的种子。
在正则表达式中,下述字符有特殊含义:
^ 在行首匹配。
$ 在行尾匹配。
. 匹配任意单个字符。
[ ] 匹配在中括号中的任意字符。
[^ ] 匹配不在中括号中的任意字符。
- 匹配任意在短横线两端字符闭区间中间的任意一个字符。
* 匹配先前模式零次或多次。
+ 匹配先前模式一次或多次。
? 匹配先前模式零次或一次。
| 匹配|两侧的任意一种模式。
() 保存一个匹配的子表达式,这个子表达式后续可以在REGEX REPLACE操作中以\n的方式引用。 它也会被所有正则表达式相关的命令所保存;包括,比如,
如果用到if( MATCHES )命令的话,这些匹配的值被保存在变量CMAKE_MATCH_(0..9)中。
CMD#75: target_link_libraries
将给定的库链接到一个目标上。
target_link_libraries(<target> [item1 [item2 [...]]] [[debug|optimized|general] <item>] ...)
为给定的目标设置连接时使用的库或者标志(flags)。如果一个库名字与工程中的另外一个目标相匹配,一个依赖关系会自动添加到构建系统中来,这样就可以在链接目标之前,保证正在被链接的库是最新的。以“-”开始,但不是“-l”或“-framework”的那些项,将会被当作链接器标志来处理。
关键字“debug”,“optimized”或者“general” 表示紧随关键字之后的库仅仅会被用到相应的构建配置上。“debug”关键字对应于调试配置(或者,如果全局属性DEBUG_CONFIGURATIONS被设置的话,就是DEBUG_CONFIGURATIONS中的名字所指定的配置)。“optimized”关键字对应于所有其他的配置类型。“general”关键字对应于所有的配置,并且纯粹是可选的(它是默认配置,可以省略)。通过创建并链接到导入库目标,可以对每种配置规则进行更细致的粒度控制。更多内容参见add_library命令的IMPORTED模式。
默认时,库之间的依赖性是可传递的。当这个目标被链接到其他目标上时,那么链接到这个目标上的库也会出现在其他目标的链接依赖上。参见LINK_INTERFACE_LIBRARIES属性的相关文档,其中有关于如何覆盖一个目标的链接依赖性传递设置的介绍。
target_link_libraries(<target> LINK_INTERFACE_LIBRARIES [[debug|optimized|general] <lib>] ...)
对于LINK_INTERFACE_LIBRARIES模式,它将会把库附加在LINK_INTERFACE_LIBRARIES以及LINK_INTERFACE_LIBRARIES在不同配置下的等价目标属性,而不是用这些库去链接。指定为“debug”的库将会被附加到LINK_INTERFACE_LIBRARIES_DEBUG属性(或者是在DEBUG_CONFIGURATIONS全局属性中列出的配置,如果DEBUG_CONFIGURATIONS被设置的话)。指定为“optimized”库将会被附加到LINK_INTERFACE_LIBRARIES属性上。指定为“general”的库(或者没有任何关键字的库),将会被当做即被指定为“debug”又被指定为“optimized”对待。
库之间的依赖图通常是非循环图(DAG),但是如果出现互相依赖的静态库,CMake会允许依赖图中包含循环依赖(强连通分支)。当其它目标链接到这些库中的一个时,CMake会重复整个连通分支。例如,代码:
add_library(A STATIC a.c) add_library(B STATIC b.c) target_link_libraries(A B) target_link_libraries(B A) add_executable(main main.c) target_link_libraries(main A)
将“main”链接到了“A B A B”。(虽然通常一次重复就足够了,但是病态对象文件以及符号排布可能需要多次重复。你可以通过在上一次target_link_libraries调用中手动重复该分支来处理这种情况。不过,如果两个归档文件确实是如此紧密的相互关联,它们可能会被合并为一个单一的归档文件。)
CMD#76: try_compile
尝试编译一些代码。
try_compile(RESULT_VAR bindir srcdir
projectName <targetname> [CMAKE_FLAGS <Flags>]
[OUTPUT_VARIABLE var])
尝试编译一个程序。在这种格式时,srcdir路径下应该包含一个完整的CMake工程,包括CMakeLists.txt文件以及所有的源文件。在该命令运行完之后,路径bindir和srcdir不会被删除。如果指定了<target name>,那么CMake将只构建那个目标;否则,目标all或ALL_BUILD将会被构建。
try_compile(RESULT_VAR bindir srcfile
[CMAKE_FLAGS <Flags>]
[COMPILE_DEFINITIONS <flags> ...]
[OUTPUT_VARIABLE var]
[COPY_FILE <filename> )
尝试编译一个srcfile。在这种情况下,用户仅仅需要提供源文件。CMake会创建合适的CMakeLists.txt文件来构建源文件。如果使用了COPY_FILE选项,编译出的文件将会被拷贝到给定的文件那里。
在这个版本里,所有在bindir/CMakeFiles/CMakeTmp文件夹下的文件,将会被自动清除;通过向CMake传递调试选项--debug-trycompile可以避免这个清除步骤。另外一些可以包含的额外标志有:INCLUDE_DIRECTORIES, LINK_DIRECTORIES, 和LINK_LIBRARIES。COMPILE_DEFINITIONS是通过-Ddefinations选项设置的预定义符号,这会传递到编译器命令行。try_compile命令在构建过程中伴随创建出的CMakeLists.txt看起来像这样:
add_definitions( <expanded COMPILE_DEFINITIONS from calling cmake>)
include_directories(${INCLUDE_DIRECTORIES})
link_directories(${LINK_DIRECTORIES})
add_executable(cmTryCompileExec sources)
target_link_libraries(cmTryCompileExec ${LINK_LIBRARIES})
在该命令的这两种版本里,如果指定了OUTPUT_VARIABLE,那么构建过程的输出会存储到给定的变量里。编译成功或失败的结果,会通过RESULT_VAR返回。CMAKE_FLAGS可以用来向正在构建的CMake传递-DVAR:TYPE = VALUE 符号。
CMD#77: try_run
尝试编译并运行某些代码。
try_run(RUN_RESULT_VAR COMPILE_RESULT_VAR
bindir srcfile [CMAKE_FLAGS <Flags>]
[COMPILE_DEFINITIONS <flags>]
[COMPILE_OUTPUT_VARIABLE comp]
[RUN_OUTPUT_VARIABLE run]
[OUTPUT_VARIABLE var]
[ARGS <arg1> <arg2>...])
尝试编译一个源文件srcfile。通过变量COMPILE_RESULT_VAR返回TRUE或者FALSE来反应编译是否失败。如果构建出了可执行文件,但是不能运行,那么RUN_RESULT_VAR会被设置为FAILED_TO_RUN。COMPILE_OUTPUT_VARIABLE变量指定了一个变量,这个变量存储了构建步骤输出的信息。RUN_OUTPUT_VARIABLE指定了一个变量,这个变量存储了运行可执行文件时的输出。出于兼容性的考虑,OUTPUT_VARIABLE还会被支持,它包含了包含编译和运行阶段的输出信息。
交叉编译相关问题
当运行交叉编译时,第一步中编译出的可执行文件通常不能在编译宿主机上直接运行。try_run()函数会检查CMAKE_CROSSCOMPILING变量来检测CMake是否是交叉编译模式。如果是的话,CMake还是会尝试编译可执行文件,但是它不会尝试运行可执行文件。相反,他会创建一些cache变量,这些变量必须由用户填充,或者在某个CMake脚本中预先设置为那些在真实目标机平台上执行的结果。这些变量有:RUN_RESULT_VAR (解释参见上文),以及如果使用了RUN_OUTPUT_VARIABLE (或者OUTPUT_VARIABLE) ,还有一个附加的cache变量RUN_RESULT_VAR__COMPILE_RESULT_VAR__TRYRUN_OUTPUT。该变量是为了保存执行过程中stdout和stderr的输出。
为了让交叉编译更加容易些,必要时再使用try_run命令。如果你使用了try_run命令,那么只有必要时才使用RUN_OUTPUT_VARIABLE(或者OUTPUT_VARIABLE)变量。在交叉编译时,使用这些变量需要cache变量必须被手动设置为可执行文件的输出。你也可以用if(CMAKE_CROSSCOMPILING)将try_run的调用“保护”起来,同时还要为这种情形给定一个易于预先设置的备选方案。
CMD#78 unset
撤销对一个变量,cache变量或者环境变量的设置。
unset(<variable> [CACHE])
删除一个指定的变量,让它变成未定义的。如果指定了CACHE选项,那么这个变量将会从cache中删除而不是当前作用域。<variable>可以是一个环境变量,比如:
unset(ENV{LD_LIBRARY_PATH})
在这个例子中,这个变量将会从当前的环境中被删除。
CMD#79 : variable_watch
监视CMake变量的改变。
variable_watch(<variable name> [<command to execute>])
如果给定的变量发生了变化,关于正在被改写的变脸的消息会被打印出来。如果指定了command选项,这条命令会被执行。这条命令会接受这样的参数:COMMAND(<variable> <access> <value> <current list file> <stack>)
CMD#80: while
当条件为真时,评估(执行)一组命令。
while(condition)
COMMAND1(ARGS ...)
COMMAND2(ARGS ...)
...
endwhile(condition)
所有在while和与之配对的endwhile之间的命令将会被记录,但并不会执行。只有当endwhile被评估,并且条件为真时,这个命令列表的记录才会被调用。条件值的评估与if命令使用相同的逻辑。