步驟 3:為程式庫新增使用需求¶
練習 1 - 為程式庫新增使用需求¶
目標使用需求 參數可以更好地控制程式庫或可執行檔的連結和包含行,同時也能更好地控制 CMake 內部目標的遞移屬性。利用使用需求的主要命令是
目標¶
為程式庫新增使用需求。
輔助材料¶
要編輯的檔案¶
MathFunctions/CMakeLists.txt
CMakeLists.txt
開始使用¶
在本練習中,我們將重構來自 Adding a Library
的程式碼,以使用現代 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
程式庫。我們將在下一步中使用該程式庫來示範 generator expressions
的常見用法。
目標¶
新增一個 INTERFACE
程式庫目標,以指定所需的 C++ 標準。
輔助資源¶
要編輯的檔案¶
CMakeLists.txt
MathFunctions/CMakeLists.txt
開始使用¶
在本練習中,我們將重構程式碼以使用 INTERFACE
程式庫來指定 C++ 標準。
從我們在步驟 3 練習 1 結束時的狀態開始此練習。您將必須完成 TODO 4
到 TODO 7
。
首先編輯頂層 CMakeLists.txt
檔案。建構一個名為 tutorial_compiler_flags
的 INTERFACE
程式庫目標,並指定 cxx_std_11
作為目標編譯器功能。
修改 CMakeLists.txt
和 MathFunctions/CMakeLists.txt
,使所有目標都具有對 tutorial_compiler_flags
的 target_link_libraries()
呼叫。
建置和執行¶
由於我們的建置目錄已從練習 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 才能建置。但請注意,使用這種方法,我們可以針對哪些目標獲得特定需求進行具體說明。此外,我們在介面程式庫中建立了一個單一的事實來源。