步驟 1:基本起點¶
我該如何開始使用 CMake?此步驟將介紹 CMake 的一些基本語法、命令和變數。在介紹這些概念時,我們將完成三個練習並建立一個簡單的 CMake 專案。
此步驟中的每個練習都將從一些背景資訊開始。然後,會提供目標和有用的資源列表。「要編輯的檔案
」區段中的每個檔案都位於 Step1
目錄中,並且包含一個或多個 TODO
註解。每個 TODO
代表要變更或新增的一兩行程式碼。這些 TODO
應按數字順序完成,首先完成 TODO 1
,然後完成 TODO 2
,依此類推。「入門
」區段將提供一些有用的提示,並引導您完成練習。然後「建置和執行
」區段將逐步說明如何建置和測試練習。最後,在每個練習的結尾,將討論預期的解決方案。
另請注意,本教學中的每個步驟都會以前一個步驟為基礎。因此,例如,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
中將 atof
替換為 std::stod
,為我們的專案新增一些 C++11 的功能。如下所示:
待辦事項 4:點擊以顯示/隱藏答案
const double inputValue = std::stod(argv[1]);
要完成 待辦事項 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
宣告。
待辦事項 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
開始使用¶
繼續編輯 Step1
中的檔案。從 待辦事項 7
開始,一直完成到 待辦事項 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
。
待辦事項 7:點擊以顯示/隱藏答案
project(Tutorial VERSION 1.0)
然後,我們使用 configure_file()
來複製輸入檔案,並取代指定的 CMake 變數。
待辦事項 8:點擊以顯示/隱藏答案
configure_file(TutorialConfig.h.in TutorialConfig.h)
由於設定的檔案將寫入專案二進位目錄中,我們必須將該目錄新增至要搜尋的包含檔案的路徑清單中。
注意:在本教學中,我們將交替提及專案建置和專案二進位目錄。它們是相同的,不代表 bin/ 目錄。
我們使用 target_include_directories()
來指定可執行檔目標應該在何處尋找包含檔案。
待辦事項 9:點擊以顯示/隱藏答案
target_include_directories(Tutorial PUBLIC
"${PROJECT_BINARY_DIR}"
)
TutorialConfig.h.in
是要設定的輸入標頭檔。當從我們的 CMakeLists.txt
呼叫 configure_file()
時,@Tutorial_VERSION_MAJOR@
和 @Tutorial_VERSION_MINOR@
的值將被取代為 TutorialConfig.h
中專案的對應版本號碼。
待辦事項 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
。
待辦事項 11:點擊以顯示/隱藏答案
#include "TutorialConfig.h"
最後,我們透過如下更新 tutorial.cxx
來列印出可執行檔名稱和版本號碼。
待辦事項 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;
}