Cmake命令之set介紹

  • 命令格式

    set(<variable> <value>... [PARENT_SCOPE]) #設置普通變量
    set(<variable> <value>... CACHE <type> <docstring> [FORCE]) #設置緩存條目
    set(ENV{<variable>} [<value>]) #設置環境變量

    ??set命令可以設置普通變量、緩存條目、環境變量三種變量的值,分別對應上述三種命令格式。set的值<value>...表示可以給變量設置0個或者多個值,當設置多個值時(大于2個),多個值會通過分號連接符連接成一個真實的值賦值給變量,當設置0個值時,實際上是把變量變為未設置狀態,相當于調用unset命令。

  • 命令解析

    下面分別對三種變量的設置進行說明。

    1. 設置普通變量

    ??命令格式set(<variable> <value>... [PARENT_SCOPE])
    ??命令含義:將變量variable設置為值<value>...,變量variable作用域為調用set命令的函數或者當前目錄,如果使用了PARENT_SCOPE選項,意味著該變量的作用域會傳遞到上一層(也就是上一層目錄或者當前函數的調用者,如果是函數則傳遞到函數的調用者,如果是目錄則傳遞到上一層目錄),并且在當前作用域該變量不受帶PARENT_SCOPE選項的set命令的影響(如果變量之前沒有定義,那么在當前作用域仍然是無定義的;如果之前有定義值,那么值和之前定義的值保持一致)。
    ??關于變量的作用域:每一個新的目錄或者函數都會創建一個新的作用域,普通變量的作用域,如果不使用PARENT_SCOPE選項,只能從外層往內層傳遞。

    • 1)先來看最常用的用法,設置變量為一個給定的值
    cmake_minimum_required (VERSION 3.10.2)
    project (set_test)
    set (normal_var a)
    message (">>> value = ${normal_var}")
    

    ??輸出為:

    >>> value = a
    
    • 2)設置變量為多個給定的值
    cmake_minimum_required (VERSION 3.10.2)
    project (set_test)
    set (normal_var a b c)
    message (">>> value = ${normal_var}")
    

    ??輸出為:

    >>> value = a;b;c
    

    ??可以看到多個值被;號連接最終的值之后賦給變量。

    • 3)設置變量為空
    cmake_minimum_required (VERSION 3.10.2)
    project (set_test)
    set (normal_var a b c)
    message (">>> value = ${normal_var}")
    set (normal_var) # 設置變量為空
    message (">>> value = ${normal_var}")
    

    ??輸出為:

    >>> value = a;b;c
    >>> value =
    
    • 4)在函數內使用選項PARENT_SCOPE,對應的作用域只能傳遞到調用它的函數。
      場景1:在函數內使用選項PARENT_SCOPE定義變量,在函數定義的文件中(非另一個函數中)使用該變量。
      結果:變量無定義。
      結論:函數內定義的變量,在函數定義的文件中調用,找不到變量的定義。
      # CMakeLists.txt
      cmake_minimum_required (VERSION 3.10.2)
      project (set_test)
      
      function (test_fn arg1)
          set (normal_var_in_fn ${arg1} PARENT_SCOPE)
      endfunction (test_fn)
      message (">>> in directory, value = ${normal_var_fn}")
      
      # 輸出
      >>> in directory, value =
      >>> in function, value =
      
      場景2:在函數內使用選項PARENT_SCOPE定義變量,在函數內使用該變量。
      結果:變量無定義。
      結論:函數內使用選項PARENT_SCOPE定義的變量,在函數內也是無定義的。
      # CMakeLists.txt
      cmake_minimum_required (VERSION 3.10.2)
      project (set_test)
      
       function (test_fn arg1)
          set (normal_var_in_fn ${arg1} PARENT_SCOPE)
          message (">>> in function, value = ${normal_var_fn}")
      endfunction (test_fn)
      
      test_fn (hello)
      
      # 輸出
      >>> in function, value =
      
      場景3:在函數內使用選項PARENT_SCOPE定義變量,在函數內使用該變量,并且使用set命令不帶PARENT_SCOPE選項定義過該變量。
      結果:函數內的變量值為不帶PARENT_SCOPE選項的set命令所定義的。
      結論:選項PARENT_SCOPE定義的變量作用域在上一層函數,當前函數的變量必須使用不帶選項PARENT_SCOPE定義。
      # CMakeLists.txt
      cmake_minimum_required (VERSION 3.10.2)
      project (set_test)
      
      function (test_fn arg1)
          set (normal_var_in_fn nohello)
          set (normal_var_in_fn ${arg1} PARENT_SCOPE)
          message (">>> in function, value = ${normal_var_in_fn}")
      endfunction (test_fn)
      test_fn (hello)
      
      # 輸出
      >>> in function, value = nohello
      
      場景4:在函數(示例中為test_fn)內使用選項PARENT_SCOPE定義變量,在另一個函數(調用者,示例中為test_fn_parent)內調用該函數。
      結果:調用者函數內有該變量的定義。
      結論:選項PARENT_SCOPE將變量傳遞到上一層調用函數。
      # CMakeLists.txt
      cmake_minimum_required (VERSION 3.10.2)
      project (set_test)
      
      function (test_fn arg1)
          set (normal_var_in_fn nohello)
          set (normal_var_in_fn ${arg1} PARENT_SCOPE)
          message (">>> in function, value = ${normal_var_in_fn}")
      endfunction (test_fn)
      
      function (test_fn_parent arg1)
          test_fn (${arg1})
          message (">>> in parent function, value = ${normal_var_in_fn}")
      endfunction (test_fn_parent)
      
      test_fn_parent (hello)
      
      # 輸出
      >>> in function, value = nohello
      >>> in parent function, value = hello
      
    • 5)在目錄內使用選項PARENT_SCOPE,對應的作用域只能傳遞到上層目錄,變量的傳遞過程與4)中函數的場景類似,不再贅述。注意一點:本例在testtest/sub下分別創建一個CMakeLists.txt文件。
      示例如下:
      # test/sub/CMakeLists.txt
      cmake_minimum_required (VERSION 3.10.2)
      project (set_sub_test)
      
      set (normal_var_in_sub_dir sub_hello)
      set (normal_var_in_sub_dir hello PARENT_SCOPE)
      
      message (">>>>>> in sub directory, value = ${normal_var_in_sub_dir}")
      
      # test/CMakeLists.txt
      cmake_minimum_required (VERSION 3.10.2)
      project (set_test)
      
      add_subdirectory (sub)
      
      message (">>> in top level, value = ${normal_var_in_sub_dir}")
      
      # 輸出
      >>>>>> in sub directory, value = sub_hello
      >>> in top level, value = hello
      
    2. 設置緩存條目

    ??命令格式set(<variable> <value>... CACHE <type> <docstring> [FORCE])
    ??命令含義:將緩存條目variable設置為值<value>...,除非用戶進行設置或使用了選項FORCE,默認情況下緩存條目的值不會被覆蓋。緩存條目可以通過CMAKE的GUI界面的add entry按鈕來增加。緩存條目的實質為可以跨層級進行傳遞的變量,類似于全局變量。
    ??緩存條目的<type>主要有以下幾類:

    • BOOL:布爾值ON/OFF,CMAKE的GUI界面對此類緩存條目會提供一個復選框。
    • FILEPATH:文件路徑,CMAKE的GUI界面對此類緩存條目會提供一個文件選擇框。
    • PATH:目錄路徑,CMAKE的GUI界面對此類緩存條目會提供一個目錄選擇框。
    • STRING / STRINGS:文本行,CMAKE的GUI界面對此類緩存條目會提供一個文本框(對應STRING)或下拉選擇框(對應STRINGS)。
    • INTERNAL:文本行,但是只用于內部,不對外呈現。主要用于運行過程中存儲變量,因此使用該type意味著使用FORCE
      ??緩存條目的幾個注意事項:
      1)如果變量先前未定義或者使用了FORCE選項,則緩存條目會直接被賦值。
      2)可以在使用cmake構建的使用通過-D選項來給緩存條目賦值,這樣CMakeLists.txt內的set命令只會為緩存條目添加類型。
      3)如果變量類型是目錄或者文件路徑,通過-D選項傳入的若只是相對路徑,那么set會給這個相對路徑前添加當前的工作目錄以變成絕對路徑(如果已經是絕對路徑則不會處理)。
      # CMakeLists.txt
      cmake_minimum_required (VERSION 3.10.2)
      project (set_test)
      
      set (cache_entry_val ON OFF CACHE BOOL "choose ON to enable")
      message (">>> value = ${cache_entry_val}")
      
      set (cache_entry_val2 ON CACHE BOOL "choose ON to enable" FORCE)
      message (">>> value2 = ${cache_entry_val2}")
      
      set (cache_entry_val3 ON)
      set (cache_entry_val3 OFF CACHE BOOL "choose ON to enable")
      message (">>> value3 = ${cache_entry_val3}")
      
      set (cache_entry_input OFF CACHE BOOL "choose ON to enable")
      message (">>> value4 = ${cache_entry_input}")
      
      set (mypath "test" CACHE FILEPATH "choose a file path")
      message (">>> value5 = ${mypath}")
      
      # 輸入cmake構建,使用-D選項
      cmake . -Dcache_entry_input=ON -Dmypath=sub
      
      # 輸出
      >>> value = ON;OFF
      >>> value2 = ON
      >>> value3 = ON
      >>> value4 = ON
      >>> value5 = /XXX/XXX/XXX/sub
      
    3. 設置環境變量

    ??命令格式set(ENV{<variable>} [<value>])
    ??命令含義:將環境變量設置為值<value>(注意沒有...),接著使用$ENV{<variable>}會得到新的值。cmake中的環境變量可以參考:環境變量
    ??環境變量設置的幾個注意事項:
    1)該命令設置的環境變量只在當前的cmake進程生效,既不會影響調用者的環境變量,也不會影響系統環境變量。
    2)如果<value>值為空或者ENV{<variable>}后沒有參數,則該命令會清除掉當前環境變量的值。
    3)<value>后的參數會被忽略。

    # CMakeLists.txt
    cmake_minimum_required (VERSION 3.10.2)
    project (set_test)
    
    message (">>> value = $ENV{CMAKE_PREFIX_PATH}")
    set (ENV{CMAKE_PREFIX_PATH} "/test/sub")
    message (">>> value = $ENV{CMAKE_PREFIX_PATH}")
    set (ENV{CMAKE_PREFIX_PATH})
    message (">>> value = $ENV{CMAKE_PREFIX_PATH}")
    set (ENV{CMAKE_PREFIX_PATH} "/test/top/") 
    message (">>> value = $ENV{CMAKE_PREFIX_PATH}")
    set (ENV{CMAKE_PREFIX_PATH} "") 
    message (">>> value = $ENV{CMAKE_PREFIX_PATH}")
    
    # 輸出
    >>> value =
    >>> value = /test/sub
    >>> value =
    >>> value = /test/top
    >>> value =
    

?


附錄:參考資料

  1. https://cmake.org/cmake/help/latest/command/set.html
  2. https://cmake.org/cmake/help/latest/manual/cmake-env-variables.7.html#manual:cmake-env-variables(7)
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,505評論 6 533
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,556評論 3 418
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,463評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,009評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,778評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,218評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,281評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,436評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,969評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,795評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,993評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,537評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,229評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,659評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,917評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,687評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,990評論 2 374