< > 翻譯 2. CMake 基礎


<<Modern CMake>> 翻譯 2. CMake 基礎

最低版本

這是每個 CMakeLists.txt 文件的第一行。CMakeLists.txt 是 CMake 所需的配置文件名稱:

cmake_minimum_required(VERSION 3.1) 

我們來了解一點 CMake 語法。 命令名稱 cmake_minimum_required 不區分大小寫,因此通常的做法是使用小寫。1 這里 VERSION 是該命令所需的特殊關鍵字。 版本號緊跟在 VERSION 關鍵字之后。 與本書中的任何其他地方一樣,你只需單擊命令名稱即可鏈接到官方文檔,然后可以使用下拉列表切換不同版本的 CMake 文檔。

這一行很特別!2 版本號也同時指明了 CMake 的行為變化。 因此,如果你設置 minimum_required 為 VERSION 2.8,在macOS上你就會獲得錯誤的鏈接行為, 例如,在最新的 CMake 版本中也是如此。 如果你把版本設置為 3.3 或更低,你會得到錯誤的符號隱藏行為,等等。 在 policies 有一個策略和版本列表。

在 CMake 3.12 中,可以這樣寫來指定支持的 CMake 版本范圍,例如 VERSION 3.1...3.12; 這意味着您最低支持 3.1,同時也測試過並支持到 3.12 的新策略。 這對於需要更好設置的用戶來說很不錯,並且由於語法上的技巧,它向后兼容舊版本的 CMake(盡管實際運行 CMake 3.2-3.11 只會在此示例中設置 3.1 版本的策略)。 新版本的策略對於 macOS 和 Windows 用戶來說往往是最重要的,他們通常也有最新版本的 CMake。

新項目應該這樣寫:

cmake_minimum_required(VERSION 3.1...3.15) if(${CMAKE_VERSION} VERSION_LESS 3.12) cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}) endif() 

如果 CMake 版本小於 3.12,則 if 塊將為 true,並且策略將設置為當前 CMake 版本。 如果 CMake 為 3.12 或更高,if 塊將為 false,此時新語法 cmake_minimum_required 將起作用,這將能夠正常工作!

警告:MSVC 的 CMake 服務器模式最初在讀取此格式時有一個 bug, 因此如果您需要支持舊版 MSVC 的非命令行 Windows 版本,則需要執行以下操作:

cmake_minimum_required(VERSION 3.1) if(${CMAKE_VERSION} VERSION_LESS 3.15) cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}) else() cmake_policy(VERSION 3.15) endif() 

 

 

如果您確實需要在此處設置較低的版本,則可以使用 cmake_policy 有條件地增加策略級別或設置特定策略。 請至少為您的 macOS 用戶執行此操作!

 

設置項目

現在,每個頂級 CMake 文件(CMakeLists.txt)都有下面這一行:

project(MyProject VERSION 1.0 DESCRIPTION "非常出色的項目" LANGUAGES CXX) 

現在我們看到了更多的新語法。 字符串被引號包圍起來,空格可多可少,項目名稱是第一個參數(位置參數)。 這里的所有的關鍵字參數都是可選的。 通過 VERSION 參數,這會設置了一堆變量,比如 MyProject_VERSION 和 PROJECT_VERSION。 LANGUAGE 可以是 C,CXX,Fortran 和 CUDA(CMake 3.7+)。 C CXX 是默認值。 在 CMake 3.9 中,DESCRIPTION 添加進來設置對項目的描述。 你可以參考 project 這個文檔。

 

 

你可以通過使用 # 開頭來添加 注釋。 CMake 也有注釋的內聯語法,但很少需要,因為空格並不重要。

 

項目名稱沒什么特別之處。此時不添加任何目標。

生成可執行文件

雖然鏈接庫更有趣,通常我們大部分時間都在生成鏈接庫,但這里我們要從一個簡單的可執行文件開始。

add_executable(one two.cpp three.h) 

這里有幾件要說明的事情。 one 是生成的可執行文件的名稱,同時也是創建的 CMake 目標的名稱(我保證你會很快聽到很多關於目標的信息)。 可執行文件名稱后緊接的是源文件列表,您可以根據需要列出任意數量的源文件列表。 CMake 很聰明,會根據文件擴展名正確識別源文件,所以列表中的頭文件會被 CMake 理解並忽略。 大多數時候,我們在源文件列表中列出頭文件的唯一原因是讓它們出現在 IDE 中。 有關通用構建系統和目標的更多信息,請參見 buildsystem

生成鏈接庫

使用 add_library 生成鏈接庫, 也是非常簡單:

add_library(one STATIC two.cpp three.h) 

您可以選擇鏈接庫類型:STATIC,SHARED 或 MODULE。 如果沒有設置,CMake 會根據變量 BUILD_SHARED_LIBS 的值在 STATIC 和 SHARED 之間選擇。

正如您將在下一節中看到的那樣,通常您需要創建一個偽目標,也就是一個不需要編譯任何文件的目標,例如,對於僅包含頭文件的庫。這也可以稱為 INTERFACE 庫; 唯一的區別是接口庫不能跟文件名。

您還可以用一個現有的鏈接庫生成一個 ALIAS 鏈接庫,該庫簡單地為您提供目標的新名稱。這樣做的一個好處是你可以生成一個名稱中帶 :: 的鏈接庫(稍后會看到)。3

配置構建目標

現在我們已經指定了目標,然后我們怎么給它添加相關信息呢?例如,它可能需要一個 include 目錄:

target_include_directories(one PUBLIC include) 

target_include_directories 將 include 目錄添加到目標. PUBLIC 對可執行文件來說意義不大; 對於一個鏈接庫,它讓 CMake 知道鏈接到這個目標的任何目標也必須包含該目錄。 其他選項是 PRIVATE(僅影響當前目標,而不影響依賴項)和 INTERFACE(僅限依賴項所需)。

現在,我們可以把目標串聯起來:

add_library(another STATIC another.cpp another.h) target_link_libraries(another PUBLIC one) 

target_link_libraries 可能是 CMake 中最有用也最令人困惑的命令。 它需要一個target(another)並添加依賴目標項。 如果名為 one 的目標不存在,則它會添加指向路徑上的一個叫做 one 鏈接庫(即命令的名稱)。 或者你可以給它一個完整的鏈接庫路徑。或鏈接器標志。 最后還有一點容易混淆的東西,那就是經典的 CMake 允許你忽略關鍵字 PUBLIC,等等。 如果目標已經鏈接完成,嘗試在鏈中進一步混合樣式,你會收到錯誤。

主要關注在任何地方使用目標和關鍵字,這就對了。

目標可以包含目錄,鏈接庫(或鏈接目標),編譯選項,編譯定義,編譯特征(參見 C++11 章節)等。 正如您將在兩個包括項目章節中看到的那樣,您通常可以使用目標(並始終制作目標)來表示所有你使用的鏈接庫。 即使那不是真正的鏈接庫的,比如 OpenMP,也可以用目標來表示。 這就是現代 CMake 很棒的原因!

開始動手實踐

看看您是否可以理解以下文件操作。 它創建了一個簡單的 C++11 鏈接庫和一個使用它的程序。 沒有依賴。 我稍后將使用 CMake 3.8 系統討論更多 C++ 標准選項。

cmake_minimum_required(VERSION 3.8) project(Calculator LANGUAGES CXX) add_library(calclib STATIC src/calclib.cpp include/calc/lib.hpp) target_include_directories(calclib PUBLIC include) target_compile_features(calclib PUBLIC cxx_std_11) add_executable(calc apps/calc.cpp) target_link_libraries(calc PUBLIC calclib) 
1. 在這本書中,我將盡可能避免向你展示錯誤的做事方式; 你可以在網上找到很多這方面的例子。我偶爾會提到替代做法,但除非絕對必要,否則不推薦這些。通常它們只是幫助您閱讀較老的 CMake 代碼。  ↩
2. 你有時會看到  FATAL_ERROR, 在 CMake <2.6 版本中,需要使用它來支持失敗,現在已經不需要了。
3.  :: 語法最初用來生成  INTERFACE IMPORTED 鏈接庫, 但是,正因為如此,大多數  target_* 命令都不適用於  IMPORTED 鏈接庫。這使得它們很難自行設置。所以現在不要使用  IMPORTED 關鍵字,請使用  ALIAS 構件目標; 這在你導出目標前都能正常工作。此限制已經在 CMake 3.11 中修復。  ↩


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM