步驟 3:為程式庫新增使用需求

練習 1 - 為程式庫新增使用需求

目標使用需求 參數可以更好地控制程式庫或可執行檔的連結和包含行,同時也能更好地控制 CMake 內部目標的遞移屬性。利用使用需求的主要命令是

目標

為程式庫新增使用需求。

輔助材料

要編輯的檔案

  • MathFunctions/CMakeLists.txt

  • CMakeLists.txt

開始使用

在本練習中,我們將重構來自 Adding a Library 的程式碼,以使用現代 CMake 方法。我們將讓程式庫定義自己的使用需求,以便在必要時將其遞移地傳遞給其他目標。在本例中,MathFunctions 將自行指定任何需要的 include 目錄。然後,使用目標 Tutorial 只需要連結到 MathFunctions,而無需擔心任何額外的 include 目錄。

起始原始碼在 Step3 目錄中提供。在本練習中,完成 TODO 1TODO 3

首先,在 MathFunctions/CMakeLists 中新增對 target_include_directories() 的呼叫。請記住,CMAKE_CURRENT_SOURCE_DIR 是目前正在處理的原始目錄的路徑。

然後,更新(並簡化!)頂層 CMakeLists.txt 中對 target_include_directories() 的呼叫。

建置和執行

建立一個名為 Step3_build 的新目錄,執行 cmake 可執行檔或 cmake-gui 來配置專案,然後使用您選擇的建置工具或透過從建置目錄中使用 cmake --build . 來建置它。以下是從命令列看起來的樣子

mkdir Step3_build
cd Step3_build
cmake ../Step3
cmake --build .

接下來,使用新建置的 Tutorial 並驗證它是否如預期般運作。

解決方案

讓我們更新上一步驟的程式碼,以使用現代 CMake 的使用需求方法。

我們想要聲明,任何連結到 MathFunctions 的人都需要包含當前原始目錄,而 MathFunctions 本身則不需要。這可以使用 INTERFACE 使用需求來表示。請記住,INTERFACE 表示消費者需要但生產者不需要的東西。

MathFunctions/CMakeLists.txt 的末尾,使用帶有 INTERFACE 關鍵字的 target_include_directories(),如下所示

TODO 1:點擊以顯示/隱藏答案
TODO 1:MathFunctions/CMakeLists.txt
target_include_directories(MathFunctions
                           INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
                           )

現在我們已經為 MathFunctions 指定了使用需求,我們可以安全地從頂層 CMakeLists.txt 中移除對 EXTRA_INCLUDES 變數的使用。

移除此行

TODO 2:點擊以顯示/隱藏答案
TODO 2:CMakeLists.txt
list(APPEND EXTRA_INCLUDES "${PROJECT_SOURCE_DIR}/MathFunctions")

並從 target_include_directories 中移除 EXTRA_INCLUDES

TODO 3:點擊以顯示/隱藏答案
TODO 3:CMakeLists.txt
target_include_directories(Tutorial PUBLIC
                           "${PROJECT_BINARY_DIR}"
                           )

請注意,使用此技術,我們的可執行目標為了使用我們的程式庫,唯一需要做的就是使用程式庫目標的名稱呼叫 target_link_libraries()。在較大的專案中,手動指定程式庫依賴關係的傳統方法很快就會變得非常複雜。

練習 2 - 使用介面程式庫設定 C++ 標準

現在我們已將程式碼切換到更現代的方法,讓我們示範一種現代技術來為多個目標設定屬性。

讓我們重構現有的程式碼以使用 INTERFACE 程式庫。我們將在下一步中使用該程式庫來示範 generator expressions 的常見用法。

目標

新增一個 INTERFACE 程式庫目標,以指定所需的 C++ 標準。

輔助資源

要編輯的檔案

  • CMakeLists.txt

  • MathFunctions/CMakeLists.txt

開始使用

在本練習中,我們將重構程式碼以使用 INTERFACE 程式庫來指定 C++ 標準。

從我們在步驟 3 練習 1 結束時的狀態開始此練習。您將必須完成 TODO 4TODO 7

首先編輯頂層 CMakeLists.txt 檔案。建構一個名為 tutorial_compiler_flagsINTERFACE 程式庫目標,並指定 cxx_std_11 作為目標編譯器功能。

修改 CMakeLists.txtMathFunctions/CMakeLists.txt,使所有目標都具有對 tutorial_compiler_flagstarget_link_libraries() 呼叫。

建置和執行

由於我們的建置目錄已從練習 1 配置完成,因此只需透過呼叫以下命令來重建我們的程式碼

cd Step3_build
cmake --build .

接下來,使用新建置的 Tutorial 並驗證它是否如預期般運作。

解決方案

讓我們更新上一步驟的程式碼,以使用介面程式庫來設定我們的 C++ 需求。

首先,我們需要移除對變數 CMAKE_CXX_STANDARDCMAKE_CXX_STANDARD_REQUIRED 的兩個 set() 呼叫。要移除的特定行如下

CMakeLists.txt
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)

接下來,我們需要建立一個介面程式庫 tutorial_compiler_flags。然後使用 target_compile_features() 來新增編譯器功能 cxx_std_11

TODO 4:點擊以顯示/隱藏答案
TODO 4:CMakeLists.txt
add_library(tutorial_compiler_flags INTERFACE)
target_compile_features(tutorial_compiler_flags INTERFACE cxx_std_11)

最後,在設定好介面程式庫後,我們需要將我們的可執行檔 Tutorial、我們的 SqrtLibrary 程式庫和我們的 MathFunctions 程式庫連結到我們新的 tutorial_compiler_flags 程式庫。相應地,程式碼將如下所示

TODO 5:點擊以顯示/隱藏答案

這個

TODO 6:點擊以顯示/隱藏答案

和這個

TODO 7:點擊以顯示/隱藏答案

這樣一來,我們所有的程式碼仍然需要 C++ 11 才能建置。但請注意,使用這種方法,我們可以針對哪些目標獲得特定需求進行具體說明。此外,我們在介面程式庫中建立了一個單一的事實來源。