-
命令格式
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}")
場景2:在函數內使用選項# 輸出 >>> in directory, value = >>> in function, value =
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)
場景3:在函數內使用選項# 輸出 >>> in function, value =
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)
場景4:在函數(示例中為# 輸出 >>> in function, value = nohello
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)中函數的場景類似,不再贅述。注意一點:本例在test
和test/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 =
?