步驟 1:基本起點¶
我該從何處開始使用 CMake?此步驟將介紹 CMake 的一些基本語法、命令和變數。在介紹這些概念的同時,我們將完成三個練習並建立一個簡單的 CMake 專案。
此步驟中的每個練習都將從一些背景資訊開始。然後,提供目標和有用的資源列表。「Files to Edit
」區段中的每個檔案都位於「Step1
」目錄中,並包含一個或多個「TODO
」註解。每個「TODO
」代表要變更或新增的一行或兩行程式碼。「TODO
」旨在按數字順序完成,首先完成「TODO 1
」,然後完成「TODO 2
」,依此類推。「Getting Started
」區段將提供一些有用的提示,並引導您完成練習。「Build and Run
」區段將逐步引導您完成建置和測試練習。「Build and Run
」區段將逐步引導您完成建置和測試練習。最後,在每個練習結束時,將討論預期的解決方案。
另請注意,本教學中的每個步驟都建立在下一個步驟的基礎上。因此,舉例來說,「Step2
」的起始程式碼是「Step1
」的完整解決方案。
練習 1 - 建置基本專案¶
最基本的 CMake 專案是從單一原始碼檔案建置的可執行檔。對於像這樣簡單的專案,只需要一個包含三個命令的「CMakeLists.txt
」檔案。
注意: 雖然 CMake 支援大寫、小寫和混合大小寫命令,但建議使用小寫命令,並且將在本教學中通篇使用。
任何專案的最上層 CMakeLists.txt 都必須先使用 cmake_minimum_required()
命令指定最低 CMake 版本。這會建立策略設定,並確保後續的 CMake 函數以相容的 CMake 版本執行。
要開始一個專案,我們使用 project()
命令來設定專案名稱。每個專案都必須呼叫此函數,且應在 cmake_minimum_required()
之後盡快呼叫。正如我們稍後將看到的,此命令也可用於指定其他專案層級資訊,例如語言或版本號碼。
最後,add_executable()
命令會告知 CMake 使用指定的原始碼檔案建立可執行檔。
目標¶
了解如何建立簡單的 CMake 專案。
有用的資源¶
要編輯的檔案¶
CMakeLists.txt
開始入門¶
「tutorial.cxx
」的原始碼在「Help/guide/tutorial/Step1
」目錄中提供,可用於計算數字的平方根。在此步驟中,不需要編輯此檔案。
在同一個目錄中,有一個「CMakeLists.txt
」檔案,您將完成它。從「TODO 1
」開始,並完成「TODO 3
」。
建置與執行¶
完成「TODO 1
」到「TODO 3
」後,我們就可以建置和執行我們的專案了!首先,執行 cmake
可執行檔或 cmake-gui
以設定專案,然後使用您選擇的建置工具來建置它。
例如,從命令列,我們可以導航到 CMake 原始碼樹狀結構的「Help/guide/tutorial
」目錄,並建立一個建置目錄
mkdir Step1_build
接下來,導航到該建置目錄並執行 cmake
以設定專案並產生原生建置系統
cd Step1_build
cmake ../Step1
然後呼叫該建置系統以實際編譯/連結專案
cmake --build .
對於多組態產生器(例如 Visual Studio),首先導航到適當的子目錄,例如
cd Debug
最後,嘗試使用新建立的「Tutorial
」
Tutorial 4294967296
Tutorial 10
Tutorial
注意: 根據 shell 的不同,正確的語法可能是「Tutorial
」、「./Tutorial
」或「.\Tutorial
」。為了簡潔起見,練習將通篇使用「Tutorial
」。
解決方案¶
如上所述,我們只需要三行「CMakeLists.txt
」即可啟動並執行。第一行是使用 cmake_minimum_required()
來設定 CMake 版本,如下所示
TODO 1:點擊以顯示/隱藏答案
cmake_minimum_required(VERSION 3.10)
建立基本專案的下一步是使用 project()
命令,如下所示設定專案名稱
TODO 2:點擊以顯示/隱藏答案
project(Tutorial)
基本專案要呼叫的最後一個命令是 add_executable()
。我們如下呼叫它
TODO 3:點擊以顯示/隱藏答案
add_executable(Tutorial tutorial.cxx)
練習 2 - 指定 C++ 標準¶
CMake 有一些特殊的變數,這些變數是在幕後建立的,或是當專案程式碼設定時對 CMake 有意義。許多這些變數都以「CMAKE_
」開頭。為您的專案建立變數時,請避免使用此命名慣例。其中兩個特殊的使用者可設定變數是 CMAKE_CXX_STANDARD
和 CMAKE_CXX_STANDARD_REQUIRED
。這些可以一起使用來指定建置專案所需的 C++ 標準。
目標¶
新增需要 C++11 的功能。
有用的資源¶
要編輯的檔案¶
CMakeLists.txt
tutorial.cxx
開始入門¶
繼續編輯「Step1
」目錄中的檔案。從「TODO 4
」開始,並完成「TODO 6
」。
首先,編輯「tutorial.cxx
」,新增需要 C++11 的功能。然後更新「CMakeLists.txt
」以要求 C++11。
建置與執行¶
讓我們再次建置我們的專案。由於我們已經為練習 1 建立了一個建置目錄並執行了 CMake,我們可以跳到建置步驟
cd Step1_build
cmake --build .
現在我們可以嘗試使用新建立的「Tutorial
」,使用與之前相同的命令
Tutorial 4294967296
Tutorial 10
Tutorial
解決方案¶
我們先在「tutorial.cxx
」中用「std::stod
」取代「atof
」,為我們的專案新增一些 C++11 功能。它看起來像這樣
TODO 4:點擊以顯示/隱藏答案
double const inputValue = std::stod(argv[1]);
要完成「TODO 5
」,只需移除「#include <cstdlib>
」即可。
我們需要在 CMake 程式碼中明確聲明它應該使用正確的標誌。在 CMake 中啟用對特定 C++ 標準支援的一種方法是使用 CMAKE_CXX_STANDARD
變數。對於本教學,請在「CMakeLists.txt
」檔案中將 CMAKE_CXX_STANDARD
變數設定為「11
」,並將 CMAKE_CXX_STANDARD_REQUIRED
設定為「True
」。請確保在呼叫 add_executable()
之前新增 CMAKE_CXX_STANDARD
宣告。
TODO 6:點擊以顯示/隱藏答案
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
練習 3 - 新增版本號碼和設定檔標頭檔¶
有時,在您的「CMakelists.txt
」檔案中定義的變數在您的原始碼中也可用可能會很有用。在這種情況下,我們想要列印專案版本。
實現此目的的一種方法是使用設定檔標頭檔。我們建立一個輸入檔案,其中包含一個或多個要替換的變數。這些變數具有特殊語法,看起來像「@VAR@
」。然後,我們使用 configure_file()
命令將輸入檔案複製到給定的輸出檔案,並將這些變數替換為「CMakelists.txt
」檔案中「VAR
」的目前值。
雖然我們可以將版本直接編輯到原始碼中,但使用此功能更佳,因為它建立單一的事實來源並避免重複。
目標¶
定義和報告專案的版本號碼。
有用的資源¶
要編輯的檔案¶
CMakeLists.txt
tutorial.cxx
TutorialConfig.h.in
開始入門¶
繼續編輯「Step1
」中的檔案。從「TODO 7
」開始,並完成「TODO 12
」。在本練習中,我們先在「CMakeLists.txt
」中新增專案版本號碼。在同一個檔案中,使用 configure_file()
將給定的輸入檔案複製到輸出檔案,並替換輸入檔案內容中的一些變數值。
接下來,建立一個輸入標頭檔「TutorialConfig.h.in
」,定義版本號碼,它將接受從 configure_file()
傳遞的變數。
最後,更新「tutorial.cxx
」以列印其版本號碼。
建置與執行¶
讓我們再次建置我們的專案。與之前一樣,我們已經建立了一個建置目錄並執行了 CMake,因此我們可以跳到建置步驟
cd Step1_build
cmake --build .
驗證在不帶任何引數的情況下執行可執行檔時,現在會報告版本號碼。
解決方案¶
在本練習中,我們透過列印版本號碼來改進我們的可執行檔。雖然我們可以完全在原始碼中完成此操作,但使用「CMakeLists.txt
」讓我們可以維護版本號碼的單一資料來源。
首先,我們修改「CMakeLists.txt
」檔案以使用 project()
命令來設定專案名稱和版本號碼。當呼叫 project()
命令時,CMake 會在幕後定義「Tutorial_VERSION_MAJOR
」和「Tutorial_VERSION_MINOR
」。
TODO 7:點擊以顯示/隱藏答案
project(Tutorial VERSION 1.0)
然後我們使用 configure_file()
來複製輸入檔案,並替換指定的 CMake 變數
TODO 8:點擊以顯示/隱藏答案
configure_file(TutorialConfig.h.in TutorialConfig.h)
由於設定檔將寫入專案二進位目錄,我們必須將該目錄新增到搜尋包含檔案的路徑清單中。
注意: 在本教學中,我們將交替使用專案建置和專案二進位目錄。這些是相同的,並非指「bin/
」目錄。
我們使用 target_include_directories()
來指定可執行檔目標應在何處尋找包含檔案。
TODO 9:點擊以顯示/隱藏答案
target_include_directories(Tutorial PUBLIC
"${PROJECT_BINARY_DIR}"
)
「TutorialConfig.h.in
」是要設定的輸入標頭檔。當從我們的「CMakeLists.txt
」呼叫 configure_file()
時,「@Tutorial_VERSION_MAJOR@
」和「@Tutorial_VERSION_MINOR@
」的值將被替換為「TutorialConfig.h
」中專案的對應版本號碼。
TODO 10:點擊以顯示/隱藏答案
// the configured options and settings for Tutorial
#define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@
#define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@
接下來,我們需要修改「tutorial.cxx
」以包含設定檔標頭檔「TutorialConfig.h
」。
TODO 11:點擊以顯示/隱藏答案
#include "TutorialConfig.h"
最後,我們透過如下更新「tutorial.cxx
」來列印可執行檔名稱和版本號碼
TODO 12:點擊以顯示/隱藏答案
if (argc < 2) {
// report version
std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "."
<< Tutorial_VERSION_MINOR << std::endl;
std::cout << "Usage: " << argv[0] << " number" << std::endl;
return 1;
}