CMake 樣式指南
我們預期所有 CMake 腳本都是:
- 在
scripts/
目錄中,或 vcpkg-*
在埠中
應遵循本檔中所述的指導方針。 現有的腳本可能尚未遵循這些指導方針;預期我們會繼續更新舊腳本,使其符合這些指導方針。
這些指導方針旨在在我們的腳本中建立穩定性。 我們希望它們能更輕鬆地向前和回溯相容性。
指導方針
除了 out 參數之外,我們一律會使用
cmake_parse_arguments()
而非函式參數或參考${ARG<N>}
。這不一定需要針對「腳本本機協助程式函式」遵循
- 在此情況下,位置參數應該放在函式宣告中(而不是使用
${ARG<N>}
),而且應該根據本機規則來命名(亦即snake_case
)。 - 例外狀況:在檢查
ARGC
之後,應透過set(argument_name "${ARG<N>}")
指定選擇性的位置參數。
- 在此情況下,位置參數應該放在函式宣告中(而不是使用
Out-parameters 應該是函式的第一個參數。 範例:
function(format out_var) cmake_parse_arguments(PARSE_ARGV 1 "arg" ...) # ... set(buffer "output") set("${out_var}" "${buffer}" PARENT_SCOPE) endfunction()
沒有未剖析或未使用的自變數。 請檢查
ARGN
或arg_UNPARSED_ARGUMENTS
。FATAL_ERROR
可能的話,WARNING
如果需要進行回溯相容性。所有
cmake_parse_arguments
都必須使用PARSE_ARGV
。所有
foreach
循環都必須使用IN LISTS
、IN ITEMS
或RANGE
。變數
${ARGV}
和${ARGN}
是未推斷的,除了對用戶的實用訊息以外。- (亦即
message(FATAL_ERROR "blah was passed extra arguments: ${ARGN}")
)
- (亦即
我們一律使用函式,而不是巨集或最上層程序代碼。
- 例外狀況:「script-local Helper 巨集」。 有時定義小型巨集會很有説明。 這應該謹慎完成,而且應該優先使用函式。
- 例外狀況:
vcpkg.cmake
『sfind_package
。
腳本樹狀結構中的腳本不應該預期在正常作業中需要可觀察的變更。
- 範例違規:
vcpkg_acquire_msys()
由於 MSYS 專案卸除舊套件,所以有需要隨著時間更新的硬式編碼套件和版本。 - 範例例外狀況:
vcpkg_from_sourceforge()
有需要維護的鏡像清單,但對呼叫端沒有可觀察的行為影響。
- 範例違規:
引用規則:CMake 中有三種自變數 - 未加上引號 ()、引號 (
foo(BAR)
foo("BAR")
) 和括弧 (foo([[BAR]])
)。 請遵循下列規則來正確加上引號:如果自變數包含變數展開
${...}
,則必須加上引號。例外狀況:當一個變數以多個自變數的形式傳遞至函式時,「splat」變數展開。 在這裡情況下,自變數應該只是
${foo}
:vcpkg_list(SET working_directory) if(DEFINED "arg_WORKING_DIRECTORY") vcpkg_list(SET working_directory WORKING_DIRECTORY "${arg_WORKING_DIRECTORY}") endif() # calls do_the_thing() if NOT DEFINED arg_WORKING_DIRECTORY, # else calls do_the_thing(WORKING_DIRECTORY "${arg_WORKING_DIRECTORY}") do_the_thing(${working_directory})
否則,如果自變數包含任何不是
\\
、\"
或\$
的逸出序列,該自變數必須是引號自變數。- 例如:
"foo\nbar"
必須加上引號。
- 例如:
否則,如果自變數包含
\
、、"
或$
,該自變數應該加上括弧。範例:
set(x [[foo\bar]]) set(y [=[foo([[bar\baz]])]=])
否則,如果自變數包含不是英數位元或
_
的字元,則應該加上該自變數的引號。否則,自變數應該未加上批注。
例外狀況:類型的
<variable|string>
自變數if()
應一律加上引號:比較運算子的兩個自變數 -
EQUAL
、STREQUAL
、VERSION_LESS
等。和的第一個自變數
MATCHES
IN_LIST
範例:
if("${FOO}" STREQUAL "BAR") # ... if("${BAZ}" EQUAL "0") # ... if("FOO" IN_LIST list_variable) # ... if("${bar}" MATCHES [[a[bcd]+\.[bcd]+]]) # ...
對於單一表達式,對於不採用
<variable|string>
的其他類型的述詞,請使用一般規則。
除了簡單的 out 參數之外,沒有 「pointer」 或 「in-out」 參數(其中使用者傳遞變數名稱而非內容)。
不會假設變數是空的。 如果變數是要在本機使用,則如果變數是字串變數,而且
vcpkg_list(SET foo)
它是清單變數,則必須明確地初始化為空白set(foo "")
。set(var)
不應該使用。 使用unset(var)
來取消設定變數、set(var "")
將它設定為空字串,並將vcpkg_list(SET var)
它設定為空清單。 注意:空字串和空白清單是相同的值;這是表示法差異,而不是結果的差異應該記錄所有預期從 API 界限的父範圍繼承的變數(亦即不是檔案本機函式)。 三重檔案中提及的所有變數都會被視為記載。
Out 參數只會在 中
PARENT_SCOPE
設定,而且永遠不會讀取。 另請參閱協助程式z_vcpkg_forward_output_variable()
,透過函式範圍轉送參數。CACHE
變數僅用於強結合函式內部共用的全域變數,以及用於單一函式內部狀態,以避免重複工作。 這些應該非常謹慎地使用,而且應該使用Z_VCPKG_
前置詞,以避免與任何其他程式碼所定義的任何局部變數發生衝突。- 例如:
vcpkg_cmake_configure
'sZ_VCPKG_CMAKE_GENERATOR
z_vcpkg_get_cmake_vars
'sZ_VCPKG_GET_CMAKE_VARS_FILE
- 例如:
include()
只有在或vcpkg-port-config.cmake
中ports.cmake
才允許 s。foreach(RANGE)
的自變數一定是自然數位,而且<start>
必須一律小於或等於<stop>
。這必須由類似下列項目來檢查:
if("${start}" LESS_EQUAL "${end}") foreach(RANGE "${start}" "${end}") ... endforeach() endif()
所有埠型腳本都必須使用
include_guard(GLOBAL)
,以避免多次包含。
需要 CMake 版本
- 除了 以外的
vcpkg.cmake
所有 CMake 腳本,都可能會假設 中的cmake_minimum_required
ports.cmake
CMake 版本。cmake_minimum_required
每次將新版的 CMake 新增至vcpkgTools.xml
時,應該都會顛簸,就像所有協助程式CMakeLists.txt
檔案中的 一樣cmake_minimum_required
。
vcpkg.cmake
一般必須假設 CMake 版本回到 3.7.2- 特定函式和選項可能會假設更大的 CMake 版本;如果這樣做,請務必使用必要的 CMake 版本來批注該函式或選項。
變更現有的函式
- 永遠不要移除非內部函式中的自變數;如果他們不應該再做任何事情,只要採取他們一樣正常,並警告使用。
- 永遠不要加入新的強制自變數。
為變數命名
cmake_parse_arguments
:將前置詞設定為"arg"
局部變數會以命名
snake_case
內部全域變數名稱前面會加上
Z_VCPKG_
。外部實驗性全域變數名稱前面會加上
X_VCPKG_
。內部函式前面會加上
z_vcpkg_
- 屬於單一函式內部的函式(亦即協助程式函式)的函式會命名
[z_]<func>_<name>
為 ,其中<func>
是其所屬協助程式函式的名稱,而<name>
是協助程式函式的作用。z_
如果沒有<func>
z_
,則應該將 新增至前端,但不要將協助程式函式z_z_foo_bar
命名為 。
- 屬於單一函式內部的函式(亦即協助程式函式)的函式會命名
公用全域變數的名稱為
VCPKG_
。