步驟 3:為函式庫新增使用需求¶
練習 1 - 為函式庫新增使用需求¶
目標的使用需求參數能更精確地控制函式庫或可執行檔的連結與包含行,同時也能更有效掌握 CMake 內部目標的遞移屬性。主要使用需求命令如下:
目標¶
為函式庫新增使用需求。
輔助教材¶
要編輯的檔案¶
MathFunctions/CMakeLists.txt
CMakeLists.txt
開始¶
在本練習中,我們將從新增 函式庫
重新編寫程式碼,以使用現代 CMake 方法。我們將讓函式庫定義自己的使用需求,以便在必要時將其遞移地傳遞給其他目標。在此情況下,MathFunctions
將自行指定任何需要的 include 目錄。然後,使用目標 Tutorial
只需要連結到 MathFunctions
,而不必擔心任何額外的 include 目錄。
起始原始程式碼位於 Step3
目錄中。在本練習中,完成 TODO 1
到 TODO 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:點擊以顯示/隱藏答案
target_include_directories(MathFunctions
INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
)
現在我們已經為 MathFunctions
指定了使用需求,我們可以安全地從頂層 CMakeLists.txt
中移除對 EXTRA_INCLUDES
變數的使用。
移除此行
TODO 2:點擊以顯示/隱藏答案
list(APPEND EXTRA_INCLUDES "${PROJECT_SOURCE_DIR}/MathFunctions")
並從 target_include_directories
中移除 EXTRA_INCLUDES
TODO 3:點擊以顯示/隱藏答案
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 4
到 TODO 7
。
首先編輯頂層的 CMakeLists.txt
檔案。建構一個名為 tutorial_compiler_flags
的 INTERFACE
函式庫目標,並指定 cxx_std_11
作為目標編譯器特性。
修改 CMakeLists.txt
和 MathFunctions/CMakeLists.txt
,使所有目標都呼叫 target_link_libraries()
來連結 tutorial_compiler_flags
。
建置並執行¶
由於我們已經從練習 1 配置了建置目錄,只需呼叫以下命令來重新建置程式碼
cd Step3_build
cmake --build .
接下來,使用新建立的 Tutorial
並驗證它是否如預期般運作。
解答¶
讓我們更新上一步驟的程式碼,使用介面函式庫來設定我們的 C++ 要求。
首先,我們需要移除對變數 CMAKE_CXX_STANDARD
和 CMAKE_CXX_STANDARD_REQUIRED
的兩個 set()
呼叫。要移除的具體行如下
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
接下來,我們需要建立一個介面函式庫 tutorial_compiler_flags
。然後使用 target_compile_features()
來新增編譯器特性 cxx_std_11
。
TODO 4:點擊以顯示/隱藏答案
add_library(tutorial_compiler_flags INTERFACE)
target_compile_features(tutorial_compiler_flags INTERFACE cxx_std_11)
最後,在設定好我們的介面函式庫之後,我們需要將我們的可執行檔 Tutorial
、我們的 SqrtLibrary
函式庫和我們的 MathFunctions
函式庫連結到我們新的 tutorial_compiler_flags
函式庫。相對應地,程式碼將如下所示
TODO 5:點擊以顯示/隱藏答案
target_link_libraries(Tutorial PUBLIC MathFunctions tutorial_compiler_flags)
這個
TODO 6:點擊以顯示/隱藏答案
target_link_libraries(SqrtLibrary PUBLIC tutorial_compiler_flags)
以及這個
TODO 7:點擊以顯示/隱藏答案
target_link_libraries(MathFunctions PUBLIC tutorial_compiler_flags)
這樣,我們所有的程式碼仍然需要 C++ 11 才能建置。但請注意,透過這種方法,我們可以指定哪些目標獲得特定要求。此外,我們在介面函式庫中建立單一事實來源。