cmake的使用--变量使用超详细详解
Variables
代碼倉(cāng)庫(kù)地址
https://github.com/zzu-andrew/linux-sys/tree/dfew/CMake為有用的參數(shù)命名
Variable Basics
像其他編程語(yǔ)言一樣,變量是CMake工作的基石。使用set()命令進(jìn)行變量的命名,變量對(duì)大小寫敏感。
set(varName value... [PARENT_SCOPE])In CMake, a variable has a particular scope, much like how variables in other languages have scope limited to a particular function, file, etc. A variable cannot be read or modified outside of its scope.
CMake treats all variables as strings.
set(myVar a b c) # myVar = "a;b;c" set(myVar a;b;c) # myVar = "a;b;c" set(myVar "a b c") # myVar = "a b c" set(myVar a b;c) # myVar = "a;b;c" set(myVar a "b c") # myVar = "a;b c"In addition, CMake doesn’t require variables to be defined before using them. Use of an undefined variable simply results in an empty string being substituted with no error or warning, much like Unix shell scripts
set(foo ab) # foo = "ab" set(bar ${foo}cd) # bar = "abcd" set(baz ${foo} cd) # baz = "ab;cd" set(myVar ba) # myVar = "ba" set(big "${${myVar}r}ef") #big = "${bar}ef"="abcdef" set(${foo} xyz) # ab = "xyz" set(bar ${notSetVar}) # bar = ""Strings are not restricted to being a single line, they can contain embedded newline characters. They can also contain quotes, which require escaping with backslashes.
set(myVar "goes here") set(multiLine "First line ${myVar} Second line with a \"quoted\" word") # Simple multi-line content with bracket syntax, # no = needed between the square bracket markers # 沒有等號(hào)的語(yǔ)法用于簡(jiǎn)單的多行文本 set(multiLine [[ First line Second line ]]) # Bracket syntax prevents unwanted substitution # 帶等號(hào)括號(hào)語(yǔ)法能阻止不必要的替換 set(shellScript [=[ #!/bin/bash [[ -n "${USER}" ]] && echo "Have USER" ]=]) # Equivalent code without bracket syntax # 特殊字符需要轉(zhuǎn)義 set(shellScript "#!/bin/bash [[ -n \"\${USER}\" ]] && echo \"Have USER\" ")As the above example shows, bracket syntax is particularly well suited to defining content like Unix shell scripts. Such content uses the ${…} syntax for its own purpose and frequently contains quotes, but using bracket syntax means these things do not have to be escaped, unlike the traditional quoting style of defining CMake content.
A variable can be unset either by calling unset() or by calling set() with no value for the named variable.
set(myVar) unset(myVar)Environment Variables
CMake允許設(shè)置環(huán)境變量,環(huán)境變量通過特殊的形式$ENV{varName}的小姑娘是設(shè)置,${varName}可以單獨(dú)的使用,環(huán)境變量設(shè)置和普通變量一樣,除了要以ENV{varName}開頭外。
set(ENV{PATH} "$ENV{PATH}:/opt/myDir")這樣設(shè)置的環(huán)境變量?jī)H僅是影響當(dāng)前的CMake,當(dāng)前CMake運(yùn)行結(jié)束之后環(huán)境變量也就跟著消失了,環(huán)境變量也只是影響Cmake階段,在build階段將不會(huì)受到影響。
Cache Variables
In addition to normal variables discussed above, CMake also supports cache variables. Unlike normal variables which have a lifetime limited to the processing of the CMakeLists.txt file, cache variables are stored in the special file called CMakeCache.txt in the build directory and they persist between CMake runs.Once set, cache variables remain set until something explicitly removes them from the cache. but the set() command is different when used to set a cache variable:
set(varName value... CACHE type "docstring" [FORCE])When the CACHE keyword is present, the set() command will apply to a cache variable named varName instead of a normal variable. The type must be one of the following:
最主要的用途是用于GUI用戶可以查看具體信息,定位問題
BOOL
ON/OFF, TRUE/FALSE, 1/0, etc.
FILEPATH
PATH
STRING
INTERNAL
The variable is not intended to be made available to the user. Internal cache variables are sometimes used to persistently record internal information by the project, such as caching the result of an intensive query or computation. GUI tools do not show INTERNAL variables.
設(shè)置boolean很頻繁,CMake中有更加簡(jiǎn)潔的專門的設(shè)置命令用于設(shè)置boolean類型的變量。
option(optVar helpString [initialValue])If initialValue is omitted, the default value OFF will be used
上述的命令等價(jià)于:
set(optVar initialValue CACHE BOOL helpString)An important difference between normal and cache variables is that the set() command will only overwrite a cache variable if the FORCE keyword is present, unlike normal variables where the set() command will always overwrite a pre-existing value.
option 命令沒有FORCE選項(xiàng),設(shè)置cache變量,會(huì)像set()命令設(shè)置普通變量一樣,默認(rèn)覆蓋原有的設(shè)置。
臨時(shí)變量和普通變量使用一樣的命名會(huì)帶來(lái)很多意料之外的結(jié)果。
set(myVar foo) # Local myVar set(result ${myVar}) # result = foo set(myVar bar CACHE STRING “”) # Cache myVarm 第二次運(yùn)行因?yàn)橐呀?jīng)存在所有這里不會(huì)再設(shè)置,除非加上 FROCEset(result ${myVar}) # First run: result = bar # Subsequent runs: result = fooset(myVar fred) set(result ${myVar}) # result = fredManipulating Cache Variables
Using set() and option(), a project can build up a useful set of customization points for its developers. Different parts of the build can be turned on or off, paths to external packages can be set, flags for compilers and linkers can be modified and so on.
Manipulating 操縱
Setting Cache Values On The Command Line
CMake allows cache variables to be manipulated directly via command line options passed to cmake.
cmake -D myVar:type=someValue ...命令行設(shè)置的變量為cache變量,能被帶有CACHE 和 FORCE選項(xiàng)的set()指令覆蓋掉,多次使用-D能設(shè)置多個(gè)臨時(shí)變量。
通過命令行設(shè)置臨時(shí)變量,socstring是空的,type類型也是可以忽略的。
cmake -D foo:BOOL=ON ... cmake -D "bar:STRING=This contains spaces" ... cmake -D hideMe=mysteryValue ... cmake -D helpers:FILEPATH=subdir/helpers.txt ... cmake -D helpDir:PATH=/opt/helpThings ...使用-U選項(xiàng)可以刪除cache,支持同時(shí)刪除多個(gè)*
cmake -U 'help*' -U foo ...CMake GUI Tools
In the first stage, the CMakeLists.txt file is read and a representation of the project is built up in memory.
This is called the configure stage. If the configure stage is successful, the generate stage can then be executed to create the build tool’s project files in the build directory. When running cmake from the command line, both stages are executed automatically, but in the GUI application, they are triggered separately with the Configure and Generate buttons.
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來(lái)直接上傳(img-JMcjL0U3-1598449461182)(picture/image-20200816124848930.png)]
設(shè)置變量,并增加變量的可選項(xiàng),經(jīng)過set_property(CACHE trafficLight PROPERTY STRINGS Red Orange Green)設(shè)置,變量trafficLight GUI上進(jìn)行編輯變量時(shí)就會(huì)出現(xiàn)設(shè)置的可選項(xiàng)。
set(trafficLight Green CACHE STRING "Status of something") set_property(CACHE trafficLight PROPERTY STRINGS Red Orange Green)In the above, the trafficLight cache variable will initially have the value Green. When the user attempts to modify trafficLight in cmake-gui, they will be given a combobox containing the three values Red, Orange and Green instead of a simple line edit widget which would otherwise have allowed them to enter any arbitrary text.
Cache variables can also have a property marking them as advanced or not. This too only affects the way the variable is displayed in cmake-gui, it does not in any way affect how CMake uses the variable during processing. By default, cmake-gui only shows non-advanced variables, which typically presents just the main variables a developer would be interested in viewing or modifying.
mark_as_advanced([CLEAR|FORCE] var1 [var2...])The CLEAR keyword ensures the variables are not marked as advanced, while the FORCE keyword ensures the variables are marked advanced. Without either keyword, the variables will only be marked as advanced if they don’t already have an advanced/non-advanced state set.
一旦標(biāo)記為advanced變量,就只能通過界面上勾選Advanced選項(xiàng)進(jìn)行查看。
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來(lái)直接上傳(img-P23h2PDu-1598449461184)(picture/image-20200816130523511.png)]
Debugging Variables And Diagnostics
使用message()命令,可以打印變量的值,可以解決當(dāng)編譯出現(xiàn)意想不到的情況時(shí)使用。
message([mode] msg1 [msg2]...) set(myVar HiThere) message("The value of myVar = ${myVar}"):This will give the following output :
andrew@ubuntu:/work/linux-sys/CMake/variables/build$ cmake ./../source/ The value of myVar = HiTheremessage中的mode選項(xiàng),可以影響打印如何輸出,甚至可以使編譯時(shí)拋出錯(cuò)誤。
STATUS
附加信息,打印信息會(huì)使用兩個(gè)連字符的方式顯示
WARNING
通常會(huì)按照高亮輸出,實(shí)測(cè)沒有效果
AUTHOR_WARNING
Like WARNING, but only shown if developer warnings are enabled (requires the -Wdev option on the cmake command line). Projects do not often use this particular type of message.
SEND_ERROR
觸發(fā)個(gè)錯(cuò)誤,并停止cmake的運(yùn)行
CMake Error at CMakeLists.txt:30 (message):The value of myVar = HiThere-- Configuring incomplete, errors occurred!FATAL_ERROR
硬件異常,立刻停止cmake,并將產(chǎn)生的日志放到CMakeOutput.log中
CMake Error at CMakeLists.txt:32 (message):The value of myVar = HiThere-- Configuring incomplete, errors occurred! See also "/work/linux-sys/CMake/variables/build/CMakeFiles/CMakeOutput.log".DEPRECATION
Special category used to log a deprecation message. If the CMAKE_ERROR_DEPRECATED variable is defined to a boolean true value, the message will be treated as an error. If CMAKE_WARN_DEPRECATED is defined to a boolean true, the message will be treated as a warning. If neither variable is defined, the message will not be shown.
If no mode keyword is provided, then the message is considered to be important information and is logged without any modification.
cmake支持變量監(jiān)控,被監(jiān)控的變量任何時(shí)候被修改都會(huì)通過消息的方式打印出來(lái)。
variable_watch(myVar [command])String Handling
隨著項(xiàng)目的復(fù)雜度增加,命令處理也會(huì)越來(lái)越復(fù)雜,cmake提供了一個(gè)強(qiáng)大的字符串處理工具string()命令,支持查找、替換、匹配、大小寫轉(zhuǎn)換、替換空格等等,
The first argument to string() defines the operation to be performed and subsequent arguments depend on the operation being requested. These arguments will generally require at least one input string and since CMake commands cannot return a value, an output variable for the result of the operation. In the material below, this output variable will generally be named outVar.
string(FIND inputString subString outVar [REVERSE])FIND searches for subString in inputString and stores the index of the found subString in outVar (the first character is index 0). The first occurrence is found unless REVERSE is specified, in which case the last occurrence will be found instead. If subString does not appear in inputString, then outVar will be given the value -1.
set(longStr abcdefabcdef) set(shortBit def) string(FIND ${longStr} ${shortBit} fwdIndex) # 反方向查找 string(FIND ${longStr} ${shortBit} revIndex REVERSE) message("fwdIndex = ${fwdIndex}, revIndex = ${revIndex}")查找之后會(huì)給出首次出現(xiàn)的字符串下標(biāo),下表從0開始
fwdIndex = 3, revIndex = 9替換字符串
string(REPLACE matchString replaceWith outVar input [input...])The REPLACE operation will replace every occurrence of matchString in the input strings with replaceWith and store the result in outVar.
set(matchString abc) set(replaceWith zzz) string(REPLACE ${matchString} ${replaceWith} replaceOutVar abcdjdiuegnkajkjfajabcabcabcdskfjksdjkabc abc) message("replace string = ${replaceOutVar}")輸出結(jié)果
replace test ============ replace string = zzzdjdiuegnkajkjfajzzzzzzzzzdskfjksdjkzzzzzz字符串后面出現(xiàn)6個(gè)z可以看出,當(dāng)給出多個(gè)input字符串的時(shí)候,會(huì)將多個(gè)字符串進(jìn)行連接之后按照一個(gè)整體輸出,因此實(shí)際使用的時(shí)候,盡量一次只替換一個(gè)字符串。
字符串處理支持正則,只需要在使用具體方法的時(shí)候在方法前面加上REGEX操作
string(REGEX MATCH regex outVar input [input...]) string(REGEX MATCHALL regex outVar input [input...]) string(REGEX REPLACE regex replaceWith outVar input [input...])The MATCH operation finds just the first match and stores it in outVar. MATCHALL finds all matches and stores them in outVar as a list.
set(longStr abcdefabcdef) string(REGEX MATCHALL "[ace]" matchVar ${longStr}) string(REGEX REPLACE "([de])" "X\\1Y" replVar ${longStr}) message("matchVar = ${matchVar}") message("replVar = ${replVar}")提取子串
string(SUBSTRING input index length outVar)input輸入的字符串, index索引字符串下標(biāo),length子串長(zhǎng)度。
如果length的值為-1,代表的是從當(dāng)前索引一直到字符串結(jié)尾
string(LENGTH input outVar) # 獲取字符串長(zhǎng)度 string(TOLOWER input outVar) # 將字符串轉(zhuǎn)換為小寫 string(TOUPPER input outVar) # 將字符串轉(zhuǎn)換為大寫 string(STRIP input outVar) # 將字符串空格剔除Lists
Lists在cmake中使用的非常普遍。
獲取列表
list(LENGTH listVar outVar) list(GET listVar index [index...] outVar)The output of the above example would be :
length = 3 letters = c;b向列表中追加和插入元素
list(APPEND listVar item [item...]) list(INSERT listVar index item [item...]) set(myList a b c) list(APPEND myList d e f) message("myList (first) = ${myList}") list(INSERT myList 2 X Y Z) message("myList (second) = ${myList}") myList (first) = a;b;c;d;e;f myList (second) = a;b;X;Y;Z;c;d;e;f查詢對(duì)應(yīng)列表的索引,可以使用以下方法
list(FIND myList value outVar) message("list test +++++++++++++++++++++") # Example set(testList a b c d e) list(FIND testList d bIndex) message("index = ${bIndex}") list test +++++++++++++++++++++ index = 3需要注意的是在FIND函數(shù)中,變量不需要在使用${}解引用
三種可以直接移除列表元素的操作,這三種操作都是直接操作列表進(jìn)行的
list(REMOVE_ITEM myList value [value...]) list(REMOVE_AT myList index [index...]) list(REMOVE_DUPLICATES myList)REMOVE_ITEM移除一個(gè)或多個(gè)指定的元素,指定的元素不存在也不會(huì)報(bào)錯(cuò)
REMOVE_AT移除指定索引的元素,元素不存在會(huì)報(bào)錯(cuò)
REMOVE_DUPLICATES確保列表中只包含獨(dú)一無(wú)二的元素
重新排序
List items can also be reordered with REVERSE or SORT operations (sorting is alphabetical):
list(REVERSE myList) list(SORT myList)Math
math(EXPR outVar mathExpr)第一個(gè)參數(shù)為固定EXPR,mathExpr定義計(jì)算過程,結(jié)果最終存儲(chǔ)在outVar中。支持+ - * / % | & ^ ~ << >> * / %.等運(yùn)算符,具體使用和C語(yǔ)言中的完全一樣。mathExpr支持使用變量${myVar}
set(x 3) set(y 7) math(EXPR z "(${x}+${y}) / 2") message("result = ${z}")Expected output:
result = 5總結(jié)
以上是生活随笔為你收集整理的cmake的使用--变量使用超详细详解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: cmake的使用--目标的编译附源码
- 下一篇: 【2016年第5期】跨社交媒体网络大数据