Cmake命令之set介紹

  • 命令格式

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

    ??set命令可以設(shè)置普通變量、緩存條目、環(huán)境變量三種變量的值,分別對應(yīng)上述三種命令格式。set的值<value>...表示可以給變量設(shè)置0個或者多個值,當(dāng)設(shè)置多個值時(大于2個),多個值會通過分號連接符連接成一個真實的值賦值給變量,當(dāng)設(shè)置0個值時,實際上是把變量變?yōu)槲丛O(shè)置狀態(tài),相當(dāng)于調(diào)用unset命令。

  • 命令解析

    下面分別對三種變量的設(shè)置進(jìn)行說明。

    1. 設(shè)置普通變量

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

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

    ??輸出為:

    >>> value = a
    
    • 2)設(shè)置變量為多個給定的值
    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)設(shè)置變量為空
    cmake_minimum_required (VERSION 3.10.2)
    project (set_test)
    set (normal_var a b c)
    message (">>> value = ${normal_var}")
    set (normal_var) # 設(shè)置變量為空
    message (">>> value = ${normal_var}")
    

    ??輸出為:

    >>> value = a;b;c
    >>> value =
    
    • 4)在函數(shù)內(nèi)使用選項PARENT_SCOPE,對應(yīng)的作用域只能傳遞到調(diào)用它的函數(shù)。
      場景1:在函數(shù)內(nèi)使用選項PARENT_SCOPE定義變量,在函數(shù)定義的文件中(非另一個函數(shù)中)使用該變量。
      結(jié)果:變量無定義。
      結(jié)論:函數(shù)內(nèi)定義的變量,在函數(shù)定義的文件中調(diào)用,找不到變量的定義。
      # 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:在函數(shù)內(nèi)使用選項PARENT_SCOPE定義變量,在函數(shù)內(nèi)使用該變量。
      結(jié)果:變量無定義。
      結(jié)論:函數(shù)內(nèi)使用選項PARENT_SCOPE定義的變量,在函數(shù)內(nèi)也是無定義的。
      # 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:在函數(shù)內(nèi)使用選項PARENT_SCOPE定義變量,在函數(shù)內(nèi)使用該變量,并且使用set命令不帶PARENT_SCOPE選項定義過該變量。
      結(jié)果:函數(shù)內(nèi)的變量值為不帶PARENT_SCOPE選項的set命令所定義的。
      結(jié)論:選項PARENT_SCOPE定義的變量作用域在上一層函數(shù),當(dāng)前函數(shù)的變量必須使用不帶選項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:在函數(shù)(示例中為test_fn)內(nèi)使用選項PARENT_SCOPE定義變量,在另一個函數(shù)(調(diào)用者,示例中為test_fn_parent)內(nèi)調(diào)用該函數(shù)。
      結(jié)果:調(diào)用者函數(shù)內(nèi)有該變量的定義。
      結(jié)論:選項PARENT_SCOPE將變量傳遞到上一層調(diào)用函數(shù)。
      # 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)在目錄內(nèi)使用選項PARENT_SCOPE,對應(yīng)的作用域只能傳遞到上層目錄,變量的傳遞過程與4)中函數(shù)的場景類似,不再贅述。注意一點:本例在testtest/sub下分別創(chuàng)建一個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. 設(shè)置緩存條目

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

    • BOOL:布爾值ON/OFF,CMAKE的GUI界面對此類緩存條目會提供一個復(fù)選框。
    • FILEPATH:文件路徑,CMAKE的GUI界面對此類緩存條目會提供一個文件選擇框。
    • PATH:目錄路徑,CMAKE的GUI界面對此類緩存條目會提供一個目錄選擇框。
    • STRING / STRINGS:文本行,CMAKE的GUI界面對此類緩存條目會提供一個文本框(對應(yīng)STRING)或下拉選擇框(對應(yīng)STRINGS)。
    • INTERNAL:文本行,但是只用于內(nèi)部,不對外呈現(xiàn)。主要用于運(yùn)行過程中存儲變量,因此使用該type意味著使用FORCE。
      ??緩存條目的幾個注意事項:
      1)如果變量先前未定義或者使用了FORCE選項,則緩存條目會直接被賦值。
      2)可以在使用cmake構(gòu)建的使用通過-D選項來給緩存條目賦值,這樣CMakeLists.txt內(nèi)的set命令只會為緩存條目添加類型。
      3)如果變量類型是目錄或者文件路徑,通過-D選項傳入的若只是相對路徑,那么set會給這個相對路徑前添加當(dāng)前的工作目錄以變成絕對路徑(如果已經(jīng)是絕對路徑則不會處理)。
      # 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構(gòu)建,使用-D選項
      cmake . -Dcache_entry_input=ON -Dmypath=sub
      
      # 輸出
      >>> value = ON;OFF
      >>> value2 = ON
      >>> value3 = ON
      >>> value4 = ON
      >>> value5 = /XXX/XXX/XXX/sub
      
    3. 設(shè)置環(huán)境變量

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

    # 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)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容