CMake學(xué)習(xí)小結(jié)--變量

CMake學(xué)習(xí)小結(jié)

參考資料

CGold的Cmake教程 -- 這個(gè)教程很新:

https://cgold.readthedocs.io/en/latest/overview.html

CMakeLists中的變量

常規(guī)變量

CMakeLists.txt中的常規(guī)變量有作用域的, 變量分以下兩種變量:

  1. 常規(guī)變量set(abc "123")
  2. 緩存變量set(abc "123" CACHE STRING ""), 在CMakeLists.txt構(gòu)造以后,會(huì)在CMakeCache.txt中有所有緩存變量的記錄.

常規(guī)變量有如下特點(diǎn):

  1. 常規(guī)變量每次重新創(chuàng)建, 沒(méi)有緩存
  2. 常規(guī)變量使用set(abc "123")的方式創(chuàng)建
  3. 其他變量要引用這個(gè)創(chuàng)建的變量,需要用解引用方法${}, 例如:set(bcd "${abc}xyz"), 此時(shí)bcd的值是123xyz
  4. 常規(guī)變量受作用域影響, 作用域的變化會(huì)產(chǎn)生父作用域和子作用域的關(guān)系, 子作用域中會(huì)繼承所有的父作用的常規(guī)變量
    1. functionadd_subdirectory 內(nèi)部會(huì)創(chuàng)建新的作用域!!!新作用域內(nèi)會(huì)繼承父作用域的變量, 改變子作用域中的變量的值,不會(huì)影響父作用域中變量的值
    2. includemacro 并不會(huì)創(chuàng)建新的作用域!!! 因此, 在這內(nèi)容中,修改變量會(huì)影響變量的值
    3. 如果在子作用域中, 如果想修改父作用域中的變量的值, 需要使用PARENT_SCOPE關(guān)鍵字 -- set(abc "786" PARENT_SCOPE). 注意這里不會(huì)改變子作用域中的abc的值, 只會(huì)修改父作用域中abc的值
  5. 常規(guī)變量使用unset(abc)來(lái)重置某個(gè)變量在當(dāng)前作用域的值
    變量以外,我們?cè)诿钚兄惺褂玫?code>-D參數(shù)也是聲明緩存變量的方式.

變量的引用于解引用${...}:

cmake_minimum_required(VERSION 2.8)
project(foo NONE)

set(a "xyz")

set(b "${a}_321")
set(${a}_1 "456")
set(variable_${a} "${a} + $臣咖 + 155")

message("b: '$'")
message("xyz_1: '${xyz_1}'")
message("variable_xyz: '${variable_xyz}'")
[usage-of-variables]> rm -rf _builds
[usage-of-variables]> cmake -Hdereference -B_builds
b: 'xyz_321'
xyz_1: '456'
variable_xyz: 'xyz + xyz_321 + 155'
-- Configuring done
-- Generating done
-- Build files have been written to: /.../usage-of-variables/_builds

嵌套使用${...}:

cmake_minimum_required(VERSION 2.8)
project(foo)

foreach(lang C CXX)
  message("Compiler for language ${lang}: ${CMAKE_${lang}_COMPILER}")
  foreach(build_type DEBUG RELEASE RELWITHDEBINFO MINSIZEREL)
    message("Flags for language ${lang} + build type ${build_type}: ${CMAKE_${lang}_FLAGS_${build_type}}")
  endforeach()
endforeach()
Compiler for language C: /usr/bin/cc
Flags for language C + build type DEBUG: -g
Flags for language C + build type RELEASE: -O3 -DNDEBUG
Flags for language C + build type RELWITHDEBINFO: -O2 -g -DNDEBUG
Flags for language C + build type MINSIZEREL: -Os -DNDEBUG
Compiler for language CXX: /usr/bin/c++
Flags for language CXX + build type DEBUG: -g
Flags for language CXX + build type RELEASE: -O3 -DNDEBUG
Flags for language CXX + build type RELWITHDEBINFO: -O2 -g -DNDEBUG
Flags for language CXX + build type MINSIZEREL: -Os -DNDEBUG

其他的例如 list 列表,常規(guī)使用比較少, 可以自己已查資料

需要小結(jié)的是:

  1. All variables have a string type
  2. List is nothing but string, elements of list separated by ;
  3. The way how variables are interpreted depends on the command
  4. Do not give same names for cache and regular variables
  5. add_subdirectory and function create new scope
  6. include and macro work in the current scope

緩存變量(全局變量)

緩存變量由如下特點(diǎn):

  1. 緩存變量是全局作用域, 變量的值會(huì)從CMakeCache.txt中獲取,緩存變量在寫入CMakeCache.txt以后, 每次都從這個(gè)緩存文件中讀取該值, 而不會(huì)重新調(diào)用set(... CACHE ...)!!!(Cache變量只會(huì)初始化一次,在CMakeCache.txt中存儲(chǔ)以后, 多次調(diào)用set(... CACHE ...)不起作用!!!)
  2. 緩存變量的常規(guī)初始化的方式是set(abc "789" CACHE STRING "")
  3. 當(dāng)常規(guī)變量和緩存變量重名時(shí), 如果緩存變量聲明在后面, 會(huì)覆蓋常規(guī)變量
  4. 除了使用set(... CACHE ...)可以聲明緩存, 也可以在命令行使用-Dxxx=xxx修改緩存變量的值!!!
  5. 如果某個(gè)Cache變量已經(jīng)存在于CMakeCache.txt中, 代碼中的set(... CACHE ...)將不會(huì)對(duì)這個(gè)值有影響, 如果我們?cè)诖a中需要強(qiáng)制修改Cache變量的值, 需要使用FORCE字段 --- set(abc "123" CACHE STRING "" FORCE)

最佳實(shí)踐, 對(duì)于全局Cache變量太多,我們最好將他們放在一個(gè)單獨(dú)的文件, 然后在調(diào)用CMake .. -C cache.cmake方法將這個(gè)文件加載進(jìn)去.

# cache.cmake

set(A "123" CACHE STRING "")
set(B "456" CACHE STRING "")
set(C "789" CACHE STRING "")
# CMakeLists.txt

cmake_minimum_required(VERSION 2.8)
project(foo NONE)

message("A: ${A}")
message("B: ${B}")
message("C: ${C}")
[usage-of-variables]> rm -rf _builds
[usage-of-variables]> cmake -C initial-cache/cache.cmake -Hinitial-cache -B_builds
loading initial cache file initial-cache/cache.cmake
A: 123
B: 456
C: 789
-- Configuring done
-- Generating done
-- Build files have been written to: /.../usage-of-variables/_builds

option() 命令創(chuàng)建的是一個(gè)緩存變量

最佳實(shí)踐, 由于Cache變量的全局性特點(diǎn), 用于做開(kāi)關(guān), 使用option:

# top-level CMakeLists.txt

cmake_minimum_required(VERSION 2.8)
project(zoo)

add_subdirectory(boo)
add_subdirectory(foo)
# foo/CMakeLists.txt

cmake_minimum_required(VERSION 2.8)
project(foo)

option(FOO_FEATURE_1 "Enable feature 1" OFF)
option(FOO_FEATURE_2 "Enable feature 2" OFF)
# boo/CMakeLists.txt

cmake_minimum_required(VERSION 2.8)
project(boo)

option(BOO_FEATURE_1 "Enable feature 1" ON)
option(BOO_FEATURE_2 "Enable feature 2" ON)

總結(jié):

  1. Use cache to set global variables
  2. Cache variables fits perfectly for expressing customized options: default value and respect user’s value
  3. Type of cache variable helps CMake-GUI users
  4. Prefixes should be used to avoid clashing because of the global nature of cache variables

環(huán)境變量 Environment variables

環(huán)境變量可以使用$ENV{...}訪問(wèn):

cmake_minimum_required(VERSION 2.8)
project(foo NONE)

message("Environment variable USERNAME: $ENV{USERNAME}")
[usage-of-variables]> rm -rf _builds
[usage-of-variables]> echo $USERNAME
ruslo
[usage-of-variables]> export USERNAME
[usage-of-variables]> cmake -Hread-env -B_builds
Environment variable USERNAME: ruslo
-- Configuring done
-- Generating done
-- Build files have been written to: /.../usage-of-variables/_builds

可以使用set(ENV{...})來(lái)設(shè)置環(huán)境變量:

cmake_minimum_required(VERSION 2.8)
project(foo NONE)

set(ENV{USERNAME} "Jane Doe")
message("Environment variable USERNAME: $ENV{USERNAME}")
[usage-of-variables]> rm -rf _builds
[usage-of-variables]> echo $USERNAME
ruslo
[usage-of-variables]> export USERNAME
[usage-of-variables]> cmake -Hset-env -B_builds
Environment variable USERNAME: Jane Doe
-- Configuring done
-- Generating done
-- Build files have been written to: /.../usage-of-variables/_builds

總結(jié):

  1. CMake can set, unset and read environment variables
  2. Check carefully configure-build steps where you set environment variables
  3. Child processes will inherit environment variables of parent
  4. Do not make your CMake code depends on environment variable if that variable may change

CMake的代碼執(zhí)行的過(guò)程

源碼樹(shù)(source-tree):

CMakeLists.txt一般會(huì)通過(guò)add_subdirectory方法給source-tree添加節(jié)點(diǎn), 而CMAKE_CURRENT_SOURCE_DIR變量就是當(dāng)前處理節(jié)點(diǎn)的全路徑, 而整個(gè)source-tree的根節(jié)點(diǎn)則是CMAKE_SOURCE_DIR.

二進(jìn)制樹(shù)(binary-tree):

在調(diào)用CMake命令編譯以后,生成的文件夾是一個(gè)編譯結(jié)果二進(jìn)制樹(shù). 其中,CMAKE_BINARY_DIR是二進(jìn)制樹(shù)的樹(shù)根, CMAKE_CURRENT_BINARY_DIR是當(dāng)前處理的二進(jìn)制樹(shù)的節(jié)點(diǎn).

CMakeLists.txt的編寫過(guò)程中, 我們可以用CMake module結(jié)合include()命令來(lái)重用代碼. 常見(jiàn)的module是*.cmake

不要用include命令加載Find*.cmake模塊!!!它有專用命令find_package

如果我們有一個(gè)專門存放的cmake module的文件夾, 我們可以將它添加到CMAKE_MODULE_PATH變量中, 最好使用list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/modules"):

# Top level CMakeLists.txt

cmake_minimum_required(VERSION 2.8)
project(foo NONE)

list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/modules")

include(MyModule)
# modules/MyModule.cmake

message("Hello from MyModule!")

除此之外, 一下是一些常用的變量:

  1. CMAKE_CURRENT_LIST_DIRCMAKE_CURRENT_LIST_FILE

可以用下面一個(gè)實(shí)例展示:

# Top-level CMakeLists.txt

cmake_minimum_required(VERSION 2.8)
project(foo NONE)

list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")

include(mymodule)
# cmake/mymodule.cmake

message("Full path to module: ${CMAKE_CURRENT_LIST_FILE}")
message("Module located in directory: ${CMAKE_CURRENT_LIST_DIR}")
[cmake-sources]> rm -rf _builds
[cmake-sources]> cmake -Hpath-to-module -B_builds
Full path to module: /.../cmake-sources/path-to-module/cmake/mymodule.cmake
Module located in directory: /.../cmake-sources/path-to-module/cmake
-- Configuring done
-- Generating done
-- Build files have been written to: /.../cmake-sources/_builds

下面一個(gè)圖表現(xiàn)幾個(gè)常見(jiàn)的變量的關(guān)系:

關(guān)系
  1. CMAKE_SOURCE_DIR/CMAKE_BINARY_DIR these variables point to the root of the source/binary trees. If your project will be added to another project as a subproject by add_subdirectory, the locations like ${CMAKE_SOURCE_DIR}/my-resource.txt will point to <top-level>/my-resource.txtinstead of <my-project>/my-resource.txt
  2. PROJECT_SOURCE_DIR/PROJECT_BINARY_DIR these variables are better then previous but still have kind of a global nature. You should change all paths related to PROJECT_SOURCE_DIR if you decide to move declaration of your project or decide to detach some part of the code and add new project command in the middle of the source tree. Consider using extra variable with clean separate purpose for such job set(FOO_MY_RESOURCES "${CMAKE_CURRENT_LIST_DIR}/resources") instead of referring to ${PROJECT_SOURCE_DIR}/resources.
  3. CMAKE_CURRENT_SOURCE_DIR this is a directory with CMakeLists.txt. If you’re using this variable internally you can substitute is with CMAKE_CURRENT_LIST_DIR. In case you’re creating module for external usage consider moving all functionality to function.

add_executable

cmake_minimum_required(VERSION 2.8)
project(foo)

add_executable(foo main.cpp)

注意這里定義的 foo是一個(gè)Target, 名稱是全局范圍的變量, 并且唯一的!!!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末住涉,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子症见,更是在濱河造成了極大的恐慌单芜,老刑警劉巖细疚,帶你破解...
    沈念sama閱讀 218,546評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異俩莽,居然都是意外死亡旺坠,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門扮超,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)价淌,“玉大人,你說(shuō)我怎么就攤上這事瞒津〔跻拢” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 164,911評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵巷蚪,是天一觀的道長(zhǎng)病毡。 經(jīng)常有香客問(wèn)我,道長(zhǎng)屁柏,這世上最難降的妖魔是什么啦膜? 我笑而不...
    開(kāi)封第一講書人閱讀 58,737評(píng)論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮淌喻,結(jié)果婚禮上僧家,老公的妹妹穿的比我還像新娘。我一直安慰自己裸删,他們只是感情好八拱,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,753評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著涯塔,像睡著了一般肌稻。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上匕荸,一...
    開(kāi)封第一講書人閱讀 51,598評(píng)論 1 305
  • 那天爹谭,我揣著相機(jī)與錄音,去河邊找鬼榛搔。 笑死诺凡,一個(gè)胖子當(dāng)著我的面吹牛东揣,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播腹泌,決...
    沈念sama閱讀 40,338評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼嘶卧,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了真屯?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 39,249評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤穷娱,失蹤者是張志新(化名)和其女友劉穎绑蔫,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體泵额,經(jīng)...
    沈念sama閱讀 45,696評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡配深,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,888評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了嫁盲。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片篓叶。...
    茶點(diǎn)故事閱讀 40,013評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖羞秤,靈堂內(nèi)的尸體忽然破棺而出缸托,到底是詐尸還是另有隱情,我是刑警寧澤瘾蛋,帶...
    沈念sama閱讀 35,731評(píng)論 5 346
  • 正文 年R本政府宣布俐镐,位于F島的核電站,受9級(jí)特大地震影響哺哼,放射性物質(zhì)發(fā)生泄漏佩抹。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,348評(píng)論 3 330
  • 文/蒙蒙 一取董、第九天 我趴在偏房一處隱蔽的房頂上張望棍苹。 院中可真熱鬧,春花似錦茵汰、人聲如沸枢里。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,929評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)坡垫。三九已至,卻和暖如春画侣,著一層夾襖步出監(jiān)牢的瞬間冰悠,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,048評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工配乱, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留溉卓,地道東北人皮迟。 一個(gè)月前我還...
    沈念sama閱讀 48,203評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像桑寨,于是被迫代替她去往敵國(guó)和親伏尼。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,960評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • CMkae主要的開(kāi)關(guān)選項(xiàng) 1尉尾,CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS 用來(lái)控制 IF ...
    jartus閱讀 1,177評(píng)論 0 0
  • 搬運(yùn)自本人 CSDN 博客:https://blog.csdn.net/ajianyingxiaoqinghan/...
    琦小蝦閱讀 15,381評(píng)論 0 11
  • CMake學(xué)習(xí) 本篇分享一下有關(guān)CMake的一些學(xué)習(xí)心得以及相關(guān)使用爆阶。 本文目錄如下: [1、CMake介紹] [...
    AlphaGL閱讀 12,246評(píng)論 11 79
  • 為了將C/C++代碼轉(zhuǎn)換為可以在硬件上運(yùn)行的程序沙咏,需要經(jīng)過(guò)編譯和鏈接辨图。編譯是將高級(jí)語(yǔ)言所寫的源程序翻譯成等價(jià)的機(jī)器...
    WalkeR_ZG閱讀 9,716評(píng)論 0 15
  • 大部分節(jié)日都洋溢著歡樂(lè)團(tuán)圓的氣氛,春節(jié)尤其如此肢藐。 在一張張?jiān)嚲碇幸魂囮嚉g聲笑語(yǔ)中故河,我們終于迎來(lái)了春節(jié),春節(jié)...
    9b54567415de閱讀 94評(píng)論 0 0