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

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

目標的使用需求參數能更精確地控制函式庫或可執行檔的連結與包含行,同時也能更有效掌握 CMake 內部目標的遞移屬性。主要使用需求命令如下:

目標

為函式庫新增使用需求。

輔助教材

要編輯的檔案

  • MathFunctions/CMakeLists.txt

  • CMakeLists.txt

開始

在本練習中,我們將從新增 函式庫重新編寫程式碼,以使用現代 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 函式庫。我們將在下一個步驟中使用該函式庫,以示範 產生器 表示式的常見用法。

目標

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

輔助資源

要編輯的檔案

  • CMakeLists.txt

  • MathFunctions/CMakeLists.txt

開始使用

在這個練習中,我們將重構我們的程式碼,使用一個 INTERFACE 函式庫來指定 C++ 標準。

從我們在練習 1 的步驟 3 結束時的狀態開始這個練習。您將需要完成 TODO 4TODO 7

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

修改 CMakeLists.txtMathFunctions/CMakeLists.txt,使所有目標都呼叫 target_link_libraries() 來連結 tutorial_compiler_flags

建置並執行

由於我們已經從練習 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 才能建置。但請注意,透過這種方法,我們可以指定哪些目標獲得特定要求。此外,我們在介面函式庫中建立單一事實來源。