使用者互動指南

簡介

當軟體套件提供基於 CMake 的建置系統及其軟體原始碼時,軟體的使用者需要執行 CMake 使用者互動工具才能建置它。

良好運作的基於 CMake 的建置系統不會在原始碼目錄中建立任何輸出,因此通常使用者會執行異地建置,並在那裡執行建置。首先,必須指示 CMake 產生合適的建置系統,然後使用者呼叫建置工具來處理產生的建置系統。產生的建置系統特定於用於產生它的機器,並且不可重新發布。提供的原始碼軟體套件的每個使用者都需要使用 CMake 來產生特定於其系統的建置系統。

產生的建置系統通常應視為唯讀。CMake 檔案作為主要工件應完整指定建置系統,並且在產生建置系統後,不應有任何理由例如在 IDE 中手動填寫屬性。CMake 將定期重寫產生的建置系統,因此使用者的修改將被覆蓋。

藉由提供 CMake 檔案,本手冊中描述的功能和使用者介面可用於所有基於 CMake 的建置系統。

當處理提供的 CMake 檔案時,CMake 工具可能會向使用者報告錯誤,例如報告編譯器不受支援,或者編譯器不支援所需的編譯選項,或者找不到相依性。這些錯誤必須由使用者通過選擇不同的編譯器、安裝 相依性,或指示 CMake 在哪裡找到它們等來解決。

命令列 cmake 工具

對於軟體原始碼的全新副本,使用 cmake(1) 的簡單但典型的用法是建立一個建置目錄並在那裡呼叫 cmake

$ cd some_software-1.4.2
$ mkdir build
$ cd build
$ cmake .. -DCMAKE_INSTALL_PREFIX=/opt/the/prefix
$ cmake --build .
$ cmake --build . --target install

建議在與原始碼不同的目錄中建置,因為這樣可以保持原始碼目錄的整潔,允許使用多個工具鏈建置單個原始碼,並允許通過簡單地刪除建置目錄來輕鬆清除建置工件。

CMake 工具可能會報告警告,這些警告旨在給軟體提供者,而不是給軟體使用者。此類警告以「This warning is for project developers」結尾。使用者可以通過將 -Wno-dev 標誌傳遞給 cmake(1) 來停用此類警告。

cmake-gui 工具

更習慣於 GUI 介面的使用者可以使用 cmake-gui(1) 工具來呼叫 CMake 並產生建置系統。

必須首先填寫原始碼和二進制目錄。始終建議為原始碼和建置使用不同的目錄。

Choosing source and binary directories

產生建置系統

有幾種使用者介面工具可用於從 CMake 檔案產生建置系統。ccmake(1)cmake-gui(1) 工具引導使用者設定各種必要的選項。cmake(1) 工具可以被呼叫以在命令列上指定選項。本手冊描述了可以使用任何使用者介面工具設定的選項,儘管對於每個工具,設定選項的模式都不同。

命令列環境

當使用命令列建置系統(如 MakefilesNinja)呼叫 cmake(1) 時,有必要使用正確的建置環境,以確保建置工具可用。CMake 必須能夠找到適當的 建置 工具、編譯器、連結器和其他所需的工具。

在 Linux 系統上,適當的工具通常在系統範圍的位置提供,並且可以通過系統套件管理器輕鬆安裝。使用者提供的或安裝在非預設位置的其他工具鏈也可以使用。

交叉編譯時,某些平台可能需要設定環境變數,或者可能提供腳本來設定環境。

Visual Studio 提供了多個命令提示字元和 vcvarsall.bat 腳本,用於為命令列建置系統設定正確的環境。雖然在使用 Visual Studio 產生器時,不一定需要使用相應的命令列環境,但這樣做沒有缺點。

當使用 Xcode 時,可以安裝多個 Xcode 版本。可以使用多種不同的方式選擇要使用的版本,但最常見的方法是

  • 在 Xcode IDE 的偏好設定中設定預設版本。

  • 通過 xcode-select 命令列工具設定預設版本。

  • 通過在運行 CMake 和建置工具時設定 DEVELOPER_DIR 環境變數來覆蓋預設版本。

為了方便起見,cmake-gui(1) 提供了環境變數編輯器。

命令列 -G 選項

CMake 預設根據平台選擇產生器。通常,預設產生器足以讓使用者繼續建置軟體。

使用者可以使用 -G 選項覆蓋預設產生器

$ cmake .. -G Ninja

cmake --help 的輸出包括 產生器 列表,供使用者選擇。請注意,產生器名稱區分大小寫。

在類 Unix 系統(包括 Mac OS X)上,預設使用 Unix Makefiles 產生器。該產生器的變體也可以在 Windows 的各種環境中使用,例如 NMake MakefilesMinGW Makefiles 產生器。這些產生器產生 Makefile 變體,可以使用 makegmakenmake 或類似工具執行。有關目標環境和工具的更多資訊,請參閱各個產生器文件。

Ninja 產生器在所有主要平台上都可用。ninja 是一個建置工具,在使用案例上類似於 make,但重點在於效能和效率。

在 Windows 上,cmake(1) 可用於為 Visual Studio IDE 產生解決方案。Visual Studio 版本可以通過 IDE 的產品名稱指定,其中包括四位數的年份。為 Visual Studio 版本有時被提及的其他方式提供了別名,例如對應於 VisualC++ 編譯器產品版本的兩位數字,或兩者的組合

$ cmake .. -G "Visual Studio 2019"
$ cmake .. -G "Visual Studio 16"
$ cmake .. -G "Visual Studio 16 2019"

Visual Studio 產生器可以針對不同的架構。可以使用 -A 選項指定目標架構

cmake .. -G "Visual Studio 2019" -A x64
cmake .. -G "Visual Studio 16" -A ARM
cmake .. -G "Visual Studio 16 2019" -A ARM64

在 Apple 上,可以使用 Xcode 產生器來為 Xcode IDE 產生專案檔案。

某些 IDE(如 KDevelop4、QtCreator 和 CLion)對基於 CMake 的建置系統提供原生支援。這些 IDE 提供使用者介面,用於選擇要使用的底層產生器,通常是在 Makefile 或基於 Ninja 的產生器之間進行選擇。

請注意,在第一次呼叫 CMake 後,無法使用 -G 更改產生器。要更改產生器,必須刪除建置目錄,並且必須從頭開始建置。

當產生 Visual Studio 專案和解決方案檔案時,在初始運行 cmake(1) 時,可以使用其他幾個選項。

可以使用 cmake -T 選項指定 Visual Studio 工具集

$ # Build with the clang-cl toolset
$ cmake.exe .. -G "Visual Studio 16 2019" -A x64 -T ClangCL
$ # Build targeting Windows XP
$ cmake.exe .. -G "Visual Studio 16 2019" -A x64 -T v120_xp

雖然 -A 選項指定了_目標_架構,但 -T 選項可用於指定所用工具鏈的詳細資訊。例如,可以給出 -Thost=x64 以選擇 64 位版本的宿主工具。以下演示了如何使用 64 位工具並為 64 位目標架構建置

$ cmake .. -G "Visual Studio 16 2019" -A x64 -Thost=x64

在 cmake-gui 中選擇產生器

「Configure」按鈕觸發一個新對話框,以選擇要使用的 CMake 產生器。

Configuring a generator

命令列上可用的所有產生器在 cmake-gui(1) 中也可用。

Choosing a generator

當選擇 Visual Studio 產生器時,還有更多選項可用於設定要產生的架構。

Choosing an architecture for Visual Studio generators

設定建置變數

軟體專案通常需要在呼叫 CMake 時在命令列上設定變數。下表列出了一些最常用的 CMake 變數

變數

含義

CMAKE_PREFIX_PATH

搜尋 相依套件的路徑

CMAKE_MODULE_PATH

搜尋其他 CMake 模組的路徑

CMAKE_BUILD_TYPE

建置配置,例如 DebugRelease,決定除錯/最佳化標誌。這僅與單一配置建置系統相關,例如 MakefileNinja。多配置建置系統(如 Visual Studio 和 Xcode 的建置系統)忽略此設定。

CMAKE_INSTALL_PREFIX

使用 install 建置目標將軟體安裝到的位置

CMAKE_TOOLCHAIN_FILE

包含交叉編譯資料(例如 工具鏈 系統根目錄)的檔案。

BUILD_SHARED_LIBS

是否為不帶類型的 add_library() 命令建置共享程式庫而不是靜態程式庫

CMAKE_EXPORT_COMPILE_COMMANDS

產生 compile_commands.json 檔案,用於 clang 基工具

CMAKE_EXPORT_BUILD_DATABASE

產生 build_database.json 檔案,用於 clang 基工具

其他專案特定的變數可用於控制建置,例如啟用或停用專案的組件。

CMake 沒有為不同提供的建置系統之間如何命名此類變數提供任何約定,除了帶有字首 CMAKE_ 的變數通常指的是 CMake 本身提供的選項,不應在第三方選項中使用,第三方選項應使用它們自己的字首。cmake-gui(1) 工具可以顯示按字首定義的分組選項,因此第三方確保他們使用自我一致的字首是有意義的。

在命令列上設定變數

CMake 變數可以在建立初始建置時在命令列上設定

$ mkdir build
$ cd build
$ cmake .. -G Ninja -DCMAKE_BUILD_TYPE=Debug

或稍後在後續呼叫 cmake(1) 時設定

$ cd build
$ cmake . -DCMAKE_BUILD_TYPE=Debug

可以使用 -U 標誌在 cmake(1) 命令列上取消設定變數

$ cd build
$ cmake . -UMyPackage_DIR

最初在命令列上建立的 CMake 建置系統可以使用 cmake-gui(1) 修改,反之亦然。

cmake(1) 工具允許指定一個檔案,以使用 -C 選項來填寫初始快取。這對於簡化重複需要相同快取條目的命令和腳本很有用。

使用 cmake-gui 設定變數

可以使用 cmake-gui 中的「Add Entry」按鈕設定變數。這會觸發一個新對話框來設定變數的值。

Editing a cache entry

可以使用 cmake-gui(1) 使用者介面的主視圖來編輯現有變數。

CMake 快取

當執行 CMake 時,它需要找到編譯器、工具和相依性的位置。它還需要能夠一致地重新產生建置系統,以使用相同的編譯/連結標誌和相依性的路徑。此類參數也需要使用者可配置,因為它們是特定於使用者系統的路徑和選項。

首次執行時,CMake 會在建置目錄中產生一個 CMakeCache.txt 檔案,其中包含此類工件的鍵值對。使用者可以通過運行 cmake-gui(1)ccmake(1) 工具來查看或編輯快取檔案。這些工具提供了互動式介面,用於重新配置提供的軟體並重新產生建置系統,這是在編輯快取值後所需要的。每個快取條目都可能具有相關的簡短幫助文本,該文本顯示在使用介面工具中。

快取條目也可能具有類型,以表示它應如何在使用者介面中呈現。例如,BOOL 類型的快取條目可以通過使用者介面中的複選框編輯,STRING 可以在文本字段中編輯,而 FILEPATH 雖然類似於 STRING,但也應提供一種使用檔案對話框定位文件系統路徑的方法。STRING 類型的條目可以提供允許值的受限列表,這些值隨後在 cmake-gui(1) 使用者介面中的下拉菜單中提供(請參閱 STRINGS 快取屬性)。

隨軟體套件一起提供的 CMake 檔案也可以使用 option() 命令定義布林切換選項。該命令建立一個具有幫助文本和預設值的快取條目。此類快取條目通常特定於提供的軟體,並且會影響建置的配置,例如是否建置測試和範例,是否啟用異常建置等。

預設集

CMake 理解一個檔案 CMakePresets.json 及其使用者特定的對應檔案 CMakeUserPresets.json,用於保存常用配置設定的預設集。這些預設集可以設定建置目錄、產生器、快取變數、環境變數和其他命令列選項。所有這些選項都可以被使用者覆蓋。CMakePresets.json 格式的完整詳細資訊在 cmake-presets(7) 手冊中列出。

在命令列上使用預設集

當使用 cmake(1) 命令列工具時,可以使用 --preset 選項呼叫預設集。如果指定了 --preset,則不需要產生器和建置目錄,但可以指定它們來覆蓋它們。例如,如果您有以下 CMakePresets.json 檔案

{
  "version": 1,
  "configurePresets": [
    {
      "name": "ninja-release",
      "binaryDir": "${sourceDir}/build/${presetName}",
      "generator": "Ninja",
      "cacheVariables": {
        "CMAKE_BUILD_TYPE": "Release"
      }
    }
  ]
}

並且您運行以下命令

cmake -S /path/to/source --preset=ninja-release

這將在 /path/to/source/build/ninja-release 中產生一個建置目錄,其中包含 Ninja 產生器,並且 CMAKE_BUILD_TYPE 設定為 Release

如果您想查看可用預設集的列表,可以運行

cmake -S /path/to/source --list-presets

這將列出 /path/to/source/CMakePresets.json/path/to/source/CMakeUsersPresets.json 中可用的預設集,而無需產生建置樹。

在 cmake-gui 中使用預設集

如果專案有可用的預設集,無論是通過 CMakePresets.json 還是 CMakeUserPresets.json,預設集列表將出現在 cmake-gui(1) 中原始碼目錄和二進制目錄之間的下拉菜單中。選擇預設集會設定二進制目錄、產生器、環境變數和快取變數,但在選擇預設集後,所有這些選項都可以被覆蓋。

呼叫建置系統

產生建置系統後,可以通過呼叫特定的建置工具來建置軟體。對於 IDE 產生器,這可能涉及將產生的專案檔案載入到 IDE 中以呼叫建置。

CMake 知道呼叫建置所需的特定建置工具,因此通常,要從命令列建置建置系統或專案(在產生後),可以在建置目錄中呼叫以下命令

$ cmake --build .

--build 旗標啟用了 cmake(1) 工具的特定操作模式。它會調用與 CMAKE_MAKE_PROGRAM 命令相關聯的 產生器,或使用者配置的建置工具。

--build 模式也接受參數 --target 來指定要建置的特定目標,例如特定的函式庫、可執行檔或自訂目標,或特定的特殊目標(如 install)。

$ cmake --build . --target myexe

在多配置產生器的情況下,--build 模式也接受 --config 參數,以指定要建置的特定配置。

$ cmake --build . --target myexe --config Release

如果產生器產生特定於配置的建置系統,且該配置是在使用 CMAKE_BUILD_TYPE 變數調用 cmake 時選擇的,則 --config 選項無效。

某些建置系統會省略建置期間調用的命令列詳細資訊。可以使用 --verbose 旗標來顯示這些命令列。

$ cmake --build . --target myexe --verbose

--build 模式也可以透過在 -- 後面列出特定的命令列選項,將其傳遞給底層的建置工具。當 CMake 沒有提供高階使用者介面來指定建置工具的選項時,例如在建置失敗的任務後繼續建置,這會很有用。

對於所有產生器,都可以在調用 CMake 後執行底層的建置工具。例如,在使用 Unix Makefiles 產生器產生之後,可以執行 make 來調用建置;或者在使用 Ninja 產生器產生之後,可以執行 ninja 等等。IDE 建置系統通常也提供用於建置專案的命令列工具,也可以調用這些工具。

選取目標

CMake 檔案中描述的每個可執行檔和函式庫都是建置目標,而建置系統可以描述自訂目標,無論是供內部使用還是供使用者使用,例如建立文件。

CMake 為所有提供 CMake 檔案的建置系統提供了一些內建目標。

all

MakefileNinja 產生器使用的預設目標。建置建置系統中的所有目標,但由其 EXCLUDE_FROM_ALL 目標屬性或 EXCLUDE_FROM_ALL 目錄屬性排除的目標除外。對於 Xcode 和 Visual Studio 產生器,名稱 ALL_BUILD 用於此目的。

help

列出可用於建置的目標。當使用 Unix MakefilesNinja 產生器時,此目標可用,且確切的輸出與工具相關。

clean

刪除已建置的物件檔案和其他輸出檔案。基於 Makefile 的產生器會為每個目錄建立一個 clean 目標,以便可以清理個別目錄。Ninja 工具提供了其自己的細緻 -t clean 系統。

test

執行測試。僅當 CMake 檔案提供基於 CTest 的測試時,此目標才會自動可用。另請參閱 執行測試

install

安裝軟體。僅當軟體使用 install() 命令定義安裝規則時,此目標才會自動可用。另請參閱 軟體安裝

package

建立二進位套件。僅當 CMake 檔案提供基於 CPack 的套件時,此目標才會自動可用。

package_source

建立原始碼套件。僅當 CMake 檔案提供基於 CPack 的套件時,此目標才會自動可用。

對於基於 Makefile 的系統,提供了二進位建置目標的 /fast 變體。/fast 變體用於建置指定的目標,而不考慮其依賴關係。不會檢查依賴關係,如果過期也不會重建。由於 Ninja 產生器在依賴關係檢查方面速度足夠快,因此未為該產生器提供此類目標。

基於 Makefile 的系統也提供建置目標來預處理、組譯和編譯特定目錄中的個別檔案。

$ make foo.cpp.i
$ make foo.cpp.s
$ make foo.cpp.o

檔案副檔名已建置到目標名稱中,因為可能存在另一個具有相同名稱但不同副檔名的檔案。但是,也提供了不帶檔案副檔名的建置目標。

$ make foo.i
$ make foo.s
$ make foo.o

在包含 foo.cfoo.cpp 的建置系統中,建置 foo.i 目標將預處理這兩個檔案。

指定建置程式

--build 模式調用的程式由 CMAKE_MAKE_PROGRAM 變數決定。對於大多數產生器,不需要配置特定的程式。

產生器

預設 make 程式

替代方案

XCode

xcodebuild

Unix Makefiles

make

NMake Makefiles

nmake

jom

NMake Makefiles JOM

jom

nmake

MinGW Makefiles

mingw32-make

MSYS Makefiles

make

Ninja

ninja

Visual Studio

msbuild

Watcom WMake

wmake

jom 工具能夠讀取 NMake 風格的 makefile 並行建置,而 nmake 工具始終串列建置。在使用 NMake Makefiles 產生器產生之後,使用者可以執行 jom 而不是 nmake。如果在使用 NMake Makefiles 產生器時,--build 模式也將使用 jom,前提是 CMAKE_MAKE_PROGRAM 已設定為 jom。為了方便起見,提供了 NMake Makefiles JOM 產生器,以常規方式尋找 jom 並將其用作 CMAKE_MAKE_PROGRAM。為了完整起見,nmake 是一個替代工具,可以處理 NMake Makefiles JOM 產生器的輸出,但這樣做會是一種效能降低。

軟體安裝

可以在 CMake 快取中設定 CMAKE_INSTALL_PREFIX 變數,以指定要安裝所提供軟體的位置。如果提供的軟體具有安裝規則(使用 install() 命令指定),它們將把成品安裝到該前綴中。在 Windows 上,預設安裝位置對應於 ProgramFiles 系統目錄,該目錄可能是特定於架構的。在 Unix 主機上,/usr/local 是預設安裝位置。

CMAKE_INSTALL_PREFIX 變數始終指向目標檔案系統上的安裝前綴。

在交叉編譯或封裝場景中,當 sysroot 為唯讀或 sysroot 應保持原始狀態時,可以將 CMAKE_STAGING_PREFIX 變數設定為實際安裝檔案的位置。

命令

$ cmake .. -DCMAKE_INSTALL_PREFIX=/usr/local \
  -DCMAKE_SYSROOT=$HOME/root \
  -DCMAKE_STAGING_PREFIX=/tmp/package
$ cmake --build .
$ cmake --build . --target install

會導致檔案安裝到主機上的路徑,例如 /tmp/package/lib/libfoo.so。主機上的 /usr/local 位置不受影響。

某些提供的軟體可能會指定 uninstall 規則,但 CMake 預設情況下不會自行產生此類規則。

執行測試

ctest(1) 工具與 CMake 發行版一起提供,用於執行提供的測試並報告結果。提供了 test 建置目標來執行所有可用的測試,但 ctest(1) 工具允許對要執行的測試、如何執行它們以及如何報告結果進行細緻的控制。在建置目錄中執行 ctest(1) 等同於執行 test 目標。

$ ctest

可以傳遞正規表示式,以僅執行與該表示式匹配的測試。若要僅執行名稱中包含 Qt 的測試:

$ ctest -R Qt

也可以透過正規表示式排除測試。若要僅執行名稱中不包含 Qt 的測試:

$ ctest -E Qt

可以透過將 -j 引數傳遞給 ctest(1) 來並行執行測試。

$ ctest -R Qt -j8

或者,可以設定環境變數 CTEST_PARALLEL_LEVEL,以避免需要傳遞 -j

預設情況下,ctest(1) 不會列印測試的輸出。命令列引數 -V (或 --verbose) 啟用詳細模式以列印所有測試的輸出。--output-on-failure 選項僅列印失敗測試的測試輸出。可以將環境變數 CTEST_OUTPUT_ON_FAILURE 設定為 1,以替代將 --output-on-failure 選項傳遞給 ctest(1)