日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Modern CMake 简介

發(fā)布時間:2023/12/20 编程问答 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Modern CMake 简介 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

作為擁有 20 年發(fā)展歷史的 CMake,肩負 Build-system Generate 的重任,被越來越多的開源庫接納,其自身理念也在不斷推陳出現(xiàn)。到底 Modern CMake 和 Traditional CMake 有什么區(qū)別,這是個值得討論的話題。

歷史背景

CMake 是一個構建系統(tǒng)生成器(build-system generator)。常見的構建系統(tǒng),有 Visual Studio,XCode,Make 等等。CMake 可以支持不同平臺下構建系統(tǒng)的生成。

CMake 的出現(xiàn)已經(jīng)有接近 20 年的歷史,它的發(fā)展過程也初步經(jīng)歷了三個階段。

  • ~2000 (~v2.x) ,剛剛啟動,過程式描述為主。
  • 2000~2014 (v3.0~) ,引入 Target 概念。
  • 2014~now (~v3.15),有了 Target 和 Property 的定義,更現(xiàn)代化。

概 述

現(xiàn)代化的 CMake 是圍繞 TargetProperty 來定義的,并且竭力避免出現(xiàn)變量 variable 的定義。Variable 橫行是典型 CMake2.8 時期的風格?,F(xiàn)代版的 CMake 更像是在遵循 OOP 的規(guī)則,通過 target 來約束 link、compile 等相關屬性的作用域。如果把一個 Target 想象成一個對象(Object),會發(fā)現(xiàn)兩者的組織方式非常相似:

  • 構造函數(shù):addexecutableaddlibrary
  • 成員函數(shù):gettargetproperty()settargetproperties()getproperty(TARGET)setproperty(TARGET)targetcompiledefinitions()targetcompilefeatures()targetcompileoptions()targetincludedirectories()targetlinklibraries()target_sources()
  • 成員變量Target properties(太多)

在 Target 中有兩個概念非常重要:Build-Requirements 和 Usage-Requirements。這兩個概念對于理解為什么現(xiàn)代 CMake 會如此設計提供了指導意義。

  • Build-Requirements: 包含了所有構建 Target必須的材料。如源代碼,include 路徑,預編譯命令,鏈接依賴,編譯/鏈接選項,編譯/鏈接特性等。

  • Usage-Requirements:包含了所有使用 Target必須的材料。如源代碼,include 路徑,預編譯命令,鏈接依賴,編譯/鏈接選項,編譯/鏈接特性等。這些往往是當另一個 Target 需要使用當前 target 時,必須包含的依賴。

    傳統(tǒng)的 CMake 和現(xiàn)代化的 CMake 的主要區(qū)別(非語法層面)如下圖所示。Traditioncal CMake 在設置 build-requirements 和 usage-requirements 上都依賴手動輸入命令,并且人工維持其作用域(變量的作用域以目錄為單位)。而 Modern CMake 在設置上述 requirement 均以 target 為單位,所以在傳遞 target 屬性到其依賴的下游鏈條中更自動也更智能。

在 Moden CMake 中新增了不少關鍵字,其中最常見的是 PUBLIC、PRIVATE、INTERFACE。

  • PRIVATE/INTERFACE/PUBLIC:定義了 Target 屬性的傳遞范圍。
  • PRIVATE: 表示 Target 的屬性只定義在當前 Target 中,任何依賴當前 Target 的 Target 不共享 PRIVATE 關鍵字下定義的屬性。
  • INTERFACE:表示 Target 的屬性不適用于其自身,而只適用于依賴其的 Target。
  • PUBLIC:表示 Target 的屬性既是 build-requirements 也是 usage-requirements。凡是依賴。凡是依賴于當前 Target 的 Target 都會共享本屬性。 -

解剖麻雀

我們來嘗試寫一個實例,看看在 CMake v3.13 及以后版本中的寫法如何。

HelloWorld |___ CMakeLists.txt |___ hello-exe |______ CMakeLists.txt |______ main.cpp |___ hello-lib |______ CMakeLists.txt |______ hello.hpp |______ hello.cpp

以這樣一個簡單的 HelloWorld 開啟有助于我們快速進入主題。這個項目結構很簡單,包含兩個子文件夾,hello-exe 生成 executable,hello-lib 生成鏈接庫(動態(tài))。

  • 我們先看下頂層 CMakeLists 的內(nèi)容:
# HelloWorld/CMakeLists.txtcmake_minimum_required(VERSION 3.14)project(HelloWorld VERSION 1.0.0)add_subdirectory(hello-lib)add_subdirectory(hello-exe)

這里沒有什么值得多討論的,與傳統(tǒng) CMake 一樣的寫法,定義 project 名稱,版本號,添加子文件夾。

  • 我們接著看 hello-lib。首先看源碼。

源碼比較簡單,只是定義一個 hello_printer 類,并在其 cpp 中定義成員函數(shù) print。請注意頭文件中的預編譯命令。這在 VS 中是非常常用的預編譯命令,用于導出動態(tài)庫的符號。而當該庫被其他 Target 調(diào)用時,需要使用 dllimport 導入符號。注意這條預編譯命令剛好符合 build-requirement 和 usage-requirement 的定義。對于 hello-lib 而言,定義 DLL_EXPORT 從而將 DLLAPI 定義為declspec(dllexport)是 build-requirement,而對于該 Target 的調(diào)用者,需要的是不定義 DLLEXPORT。因而需要在定義 compile_definitions 時將 DllEXPORT 放在 PRIVATE 關鍵詞下。

當其他 Target 使用 hello-lib 的時候,還需要知道 hello.hpp 的路徑。傳統(tǒng)的 CMake 寫法是通過在調(diào)用者的 CMakeLists.txt 中添加 includedirectory 來實現(xiàn)。但這種寫法會依賴庫之間的相對路徑,一旦調(diào)整路徑,所有的 CMakeLists 都將需要更新。在 Modern CMake 中不必如此,你只需要通過 targetincludedirectories 指定 hello.hpp 的路徑,將之納入 INTERFACE(當然 PUBLIC)也行。則調(diào)用者就可以得到該 include 路徑。

CMakeLists.txt 全文如下:

set(target_name "hello-lib")add_library(${target_name} SHARED hello.cpp hello.hpp )target_include_directories(${target_name} INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})target_compile_definitions(${target_name} PRIVATE Dll_EXPORT)
  • 最后看下 hello-exe。hello-exe 中的 CMakeLists.txt 就可以比較簡單了:
add_executable(hello-exe main.cpp)target_link_libraries(hello-exe PUBLIC hello-lib)

補充

Modern CMake 中還有些有意思的知識點,這里沒法一一覆蓋,只能稍稍展開。最有意思的點是 generator-expression。在現(xiàn)代 IDE 中,Build-type 一般都不是在 CMake config 期間能確定的。如 VS,XCode 都支持 Multi-configuration,具體使用 Debug 還是 Release 是在編譯時才確定,那如果 Target 的依賴路徑或者依賴庫需要區(qū)分 Configuration 來配置該怎么辦呢?在傳統(tǒng) CMake 中是比較難辦的,target_link_libraries 提供了一種手段,可以用 debug 和 optimized 來區(qū)分具體的庫名,而其他的編譯或鏈接設置則比較困難。在 Modern CMake 中,我們可以通過 generator-expression 來實現(xiàn)。

generator-expression 定義為$<...>的形式。該表達式的值有多種形式,而且支持嵌套使用:

  • 條件表達式
  • $\ 當條件為 1 時,表達式為 true_string,否則為空
  • $\ 當條件為 1 時,表達式為 true_string,否則為 false_string
  • 變量表達式
  • $ 當 target 存在為 1,否則為 0
  • $\ 當 config 為 cfg 時為 1,否則為 0。這是非常高頻使用的一個表達式,可以通過它來區(qū)分 Debug/Release 等不同的 config。如下例所示,通過嵌套使用上述兩個表達式,可以達到區(qū)分 CONFIG 來設置依賴庫路徑的目的。
target_link_directories(${PROJECT_NAME} PUBLIC $<$<CONFIG:Debug>:${CONAN_LIB_DIRS_DEBUG}> $<$<CONFIG:Release>:${CONAN_LIB_DIRS_RELEASE}>)
  • ... 太多了,不一一列舉。以上是 Modern CMake 中常用的內(nèi)容,還有些如 IMPORTED,ALIAS 暫時還沒用到,等用到再更新吧。

參考

  • https://crascit.com/2016/01/31/enhanced-source-file-handling-with-target_sources/#comment-414
  • https://github.com/onqtam/awesome-cmake/blob/master/README.md
  • https://www.youtube.com/watch?v=y7ndUhdQuU8

本文首發(fā)于 GitChat,未經(jīng)授權不得轉(zhuǎn)載,轉(zhuǎn)載需與 GitChat 聯(lián)系。

閱讀全文: http://gitbook.cn/gitchat/activity/5d4cbaf5f84543415feac3ee

您還可以下載 CSDN 旗下精品原創(chuàng)內(nèi)容社區(qū) GitChat App , GitChat 專享技術內(nèi)容哦。

總結

以上是生活随笔為你收集整理的Modern CMake 简介的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。