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()
      
  • 沒有未剖析或未使用的自變數。 請檢查 ARGNarg_UNPARSED_ARGUMENTSFATAL_ERROR 可能的話, WARNING 如果需要進行回溯相容性。

  • 所有 cmake_parse_arguments 都必須使用 PARSE_ARGV

  • 所有 foreach 循環都必須使用 IN LISTSIN ITEMSRANGE

  • 變數 ${ARGV}${ARGN} 是未推斷的,除了對用戶的實用訊息以外。

    • (亦即 message(FATAL_ERROR "blah was passed extra arguments: ${ARGN}")
  • 我們一律使用函式,而不是宏或最上層程序代碼。

    • 例外狀況:「script-local Helper 宏」。 有時定義小型宏會很有説明。 這應該謹慎完成,而且應該優先使用函式。
    • 例外狀況: vcpkg.cmake『s find_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()應一律加上引號:

      • 比較運算子的兩個自變數 - EQUALSTREQUALVERSION_LESS等。

      • 和的第一個自變數MATCHESIN_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's Z_VCPKG_CMAKE_GENERATOR
      • z_vcpkg_get_cmake_vars's Z_VCPKG_GET_CMAKE_VARS_FILE
  • include()只有在或 vcpkg-port-config.cmakeports.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_requiredports.cmakeCMake 版本。
    • 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_