cmake的使用-if-else的逻辑流程详解

Flow Controls

代码仓库地址

https://github.com/zzu-andrew/linux-sys/tree/dfew/CMake 

The ubiquitous if() command provides the expected if-then-else behavior and looping is provided through the foreach() and while() commands.

The if() Command

if(expression1)
# commands ...
elseif(expression2)
# commands ...
else()
# commands ...
endif()

Basic Expressions

最简单的if语句是如下:

if(value)
  • value是数值1、ON、YES、TRUE、Y或者一个非空的数值都被认为是真,test对大小写不敏感。
  • value是数值0、NO、OFF、FALSE、N、IGNORE、NOTFPOUND、空字符串或者以-NOTFOUND结尾的字符串的时候,被认为是假,判别假的时候value同样大小写不敏感
  • 如果不是上述两种情况,将会被认为是一个变量名,或者后面会说明的过程

忽略endif()的示例:

# Examples of unquoted constants
if(YES)
if(0)
if(TRUE)
# These are also treated as unquoted constants because the
# variable evaluation occurs before if() sees the values
set(A YES)
set(B 0)
if(${A}) # Evaluates to true
if(${B}) # Evaluates to false
# Does not match any of the true or false constants, so proceed
# to testing as a variable name in the fall through case below
if(someLetters)
# Quoted value, so bypass the true/false constant matching
# and fall through to testing as a variable name or string
if("someLetters")
# Common pattern, often used with variables defined
# by commands such as option(enableSomething "...")
if(enableSomething)
# ...
endif()

Logic Operators

CMake supports the usual AND, OR and NOT logical operators, as well as parentheses to control order of precedence.

# Logical operators
if(NOT expression)
if(expression1 AND expression2)
if(expression1 OR expression2)
# Example with parentheses
if(NOT (expression1 AND (expression2 OR expression3)))

按照通常的约定,首先计算括号内的表达式,从最里面的括号开始。

Comparison Tests

CMake将比较测试分为三种不同的类型:数字、字符串和版本号,但是语法形式都遵循相同的模式。

if(value1 OPERATOR value2)

value1value2可以是变量名或值。如果一个值与一个变量名一样,将会被视为一个变量,否则将会被视为字符串或者值。

OPERATOR总结:

NumericStringVersion numbers
LESSSTRLESSVERSION_LESS
GREATERSTRGREATERVERSION_GREATER
EQUALSTREQUALVERSION_EQUAL
LESS_EQUALSTRLESS_EQUALVERSION_LESS_EQUAL
GREATER_EQUALSTRGREATER_EQUALVERSION_GREATER_EQUAL

当比对的是含有字符和数字的混合情况,比对结果是未定义的,根据具体的CMake版本

# Valid numeric expressions, all evaluating as true
if(2 GREATER 1)
if("23" EQUAL 23)
set(val 42)
if(${val} EQUAL 42)
if("${val}" EQUAL 42)
# Invalid expression that evaluates as true with at
# least some CMake versions. Do not rely on this behavior.
if("23a" EQUAL 23)

版本号对比,次版本号没有给出就默认为0

if(1.2  VERSION_EQUAL 1.2.0)
if(1.2  VERSION_LESS 1.2.3)
if(1.2.3  VERSION_GREATER 1.2)
if(2.0.1  VERSION_GREATER 1.9.7)
if(1.8.2  VERSION_LESS 2)*

字符串对比支持正则比对,但是支持简单的正则比对

if(value MATCHES regex)
if("Hi from ${who}" MATCHES "Hi from (Fred|Barney).*")
	message("${CMAKE_MATCH_1} says hello")
endif()

File System Tests

CMake中有一系列文件测试函数,IS_NEWER_THAN当两个文件时间戳一样或者一个文件丢失的时候都会返回true

if(EXISTS pathToFileOrDir)
if(IS_DIRECTORY pathToDir)
if(IS_SYMLINK fileName)
if(IS_ABSOLUTE path)
if(file1 IS_NEWER_THAN file2)

Existence Tests

大型和复杂工程中经常使用,用于决定哪些需要使用哪些不需要

if(DEFINED name)
if(COMMAND name)
if(POLICY name)
if(TARGET name)
if(TEST name) # Available from CMake 3.4 onward

Each of the above will return true if an entity of the specified name exists at the point where the if command is issued.

DEFINED

如果对应的name定义了就返回true,用于测试变量或者环境变量是否被定义了

if(DEFINED SOMEVAR)       # Checks for a CMake variable
if(DEFINED ENV{SOMEVAR})  # Checks for an environment variable

COMMAND

测试对应的name是否是CMake的命令,函数或者宏。

POLICY

测试特定的策略是否是已知,通常的形式是 CMPxxxxxxxx部分通常是数字

TARGET

当一个目标被add_executable(), add_library() or add_custom_target()其中之一定义的时候,会返回true

TEST

add_test()定义之后会返回true

CMake3.5以上支持以下语句

if(value IN_LIST listVar)

Common Examples

if(WIN32)
    set(platformImpl source_win.cpp)
else()
    set(platformImpl source_generic.cpp)
endif()

message("platformImpl = ${platformImpl} WIN32 = ${WIN32}")

expect output:

platformImpl = source_generic.cpp WIN32 = 
if(MSVC)
	set(platformImpl source_msvc.cpp)
else()
	set(platformImpl source_generic.cpp)
endif()
if(APPLE)
# Some Xcode-specific settings here...
else()
# Things for other platforms here...
endif()
if(CMAKE_GENERATOR STREQUAL "Xcode")
# Some Xcode-specific settings here...
else()
# Things for other CMake generators here...
endif()

设置变量作为一个库是否编译的开关

option(BUILD_MYLIB "Enable building the myLib target" ON)
	if(BUILD_MYLIB)
	add_library(myLib src1.cpp src2.cpp)
endif()

Looping

使用循环,持续进行检测,直到特定的环境发生

foreach()
foreach(loopVar arg1 arg2 ...)
# ...
endforeach()

In the above form, for each argN value, loopVar is set to that argument and the loop body is executed.

Rather than listing out each item explicitly, the arguments can also be specified by one or more list variables using the more general form of the command:

foreach(loopVar IN [LISTS listVar1 ...] [ITEMS item1 ...])
# ...
endforeach()

示例如下:

set(list1 A B)
set(list2)
set(foo WillNotBeShown)
foreach(loopVar IN LISTS list1 list2 ITEMS foo bar)
	message("Iteration for: ${loopVar}")
endforeach()

output:

Iteration for: A 
Iteration for: B
Iteration for: foo
Iteration for: bar

当在数值型中使用foreach时,可以使用类C风格

foreach(loopVar RANGE start stop [step])

默认的step为1,也就是从start开始每次+1直到值大于stop停止循环。

foreach(loopVar RANGE 1 10 6)
    message("echo loopVar = ${loopVar}")
endforeach()

output:

echo loopVar = 1
echo loopVar = 7

同时也支持单个value形式的,如下:

foreach(loopVar RANGE value)

等价于foreach(loopVar RANGE 0 value)

while()
while(condition)
# ...
endwhile()

执行到conditiontrue为止

Interrupting Loops

Both while() and foreach() loops support the ability to exit the loop early with break() or to skip to the start of the next iteration with continue().

foreach(outerVar IN ITEMS a b c)
    unset(s)
    foreach(innerVar IN ITEMS 1 2 3)
        # Stop inner loop once string s gets long
        list(APPEND s "${outerVar}${innerVar}")
        string(LENGTH s length)
        if(length GREATER 5)
       		break()
        endif()
        # Do no more processing if outer var is "b"
        if(outerVar STREQUAL "b")
        	continue()
        endif()
        message("Processing ${outerVar}-${innerVar}")
    endforeach()
    message("Accumulated list: ${s}")
endforeach()

output:

Processing a-1
Processing a-2
Processing a-3
Accumulated list: a1;a2;a3
Accumulated list: b1;b2;b3
Processing c-1
Processing c-2
Processing c-3
Accumulated list: c1;c2;c3
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Achilles.Wang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值