cmake的使用-if-else的逻辑流程详解
Flow Controls
代碼倉庫地址
https://github.com/zzu-andrew/linux-sys/tree/dfew/CMakeThe 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)value1和value2可以是變量名或值。如果一個值與一個變量名一樣,將會被視為一個變量,否則將會被視為字符串或者值。
OPERATOR總結:
| LESS | STRLESS | VERSION_LESS |
| GREATER | STRGREATER | VERSION_GREATER |
| EQUAL | STREQUAL | VERSION_EQUAL |
| LESS_EQUAL | STRLESS_EQUAL | VERSION_LESS_EQUAL |
| GREATER_EQUAL | STRGREATER_EQUAL | VERSION_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 onwardEach 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 variableCOMMAND
測試對應的name是否是CMake的命令,函數或者宏。
POLICY
測試特定的策略是否是已知,通常的形式是 CMPxxxx, xxxx部分通常是數字
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()執行到condition非true為止
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 longlist(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總結
以上是生活随笔為你收集整理的cmake的使用-if-else的逻辑流程详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【2017年第3期】从点状应用到大数据统
- 下一篇: C/C++实现读取当前文件夹下的文件-p