色婷婷狠狠18禁久久YY,CHINESE性内射高清国产,国产女人18毛片水真多1,国产AV在线观看

Cmake如何入門?

劉姿婷2年前20瀏覽0評論

WhyCMake?

先回答括號中的問題:被逼的。

這三個字是認真的。

不管CMake是否是一個優秀的構建工具,不管你是否認同CMake,都無法否認CMake目前是C++的defactobuildsystem[1]。

所以在社區以及生態的影響下,使用CMake作為構建工具的項目會越來越多。

一個佐證是,即使是微軟、Google以及Facebook這三家公司都有自己的C++構建系統,他們開源的項目仍支持使用CMake構建;并且CMake是除了官方構建系統之外的推薦構建系統。

如何學習CMake

首先反對認為CMake不需要入門的觀點:

cmake還需要入門?這種工具性質的東西,你只要用到哪里學到哪里就行了,如果需要入門那就說明這個工具做的不怎么樣。

這句話后半句是符合事實的,CMake這個工具不僅是做的不怎么樣,而且做的....一言難盡....以至于這個問題下就有回答說不要跳CMake這個坑的;更多的吐槽可以參考如何評價CMake這個問題。

所以自CMakev3.0開始(嚴格的來說是v3.2[2]),社區開始了浩浩蕩蕩的ModernCMake的運動,試圖通過引入一些新的特性并搭配推薦做法來提升用戶的生活質量。

嗯,另一個廣泛喊著modernization的社區剛好是C++社區...

又恰好這倆的現代化用法的相同之處在于需要摒棄老的、傳統的觀念&使用方法,使用新的、現代化的慣用法。

打一個可能不太準的比喻:說CMake用到哪學到哪就行了和說C++用到哪學到哪就行了一樣;如果你本身對這塊領域已經很有經驗,那么這樣做是沒問題的;但是對于一個新人來說,無異于讓他自己去踩雷。

另一個上來就直接扔給對方一個CMakedocumentation讓他學的做法也是非常糟糕的;這就好比一個新手說要學習C++,你直接朝他扔了cppreference...

學習(Modern)CMake的合適路徑

0x00起手式

這里假設題主以及其他想入門CMake的人像我一樣鶸,下面是我個人總結的比較適合的學習路徑。

首先默念三遍并記住口訣:

Declareatarget

Declaretarget'straits

It'sallaboutt

然后clonehttps://github.com/ttroy50/cmake-examples這個項目到本地,把里面的

01-basic(跳過E-installing,因為和依賴有關,后面會說)

02-sub-projects

兩個目錄認真的學習一遍,最好自己能夠動手跟著做一遍。

每學習完一個小節,把前面的三句口訣復習一下

每遇到一個不認識的命令,在EffectiveModernCMake這個頁面里搜索一下,看看這個命令是否取代了某個老命令。

cmake-examples這個項目大概是我在Github上能找到的最符合“深入淺出”這四個字的。不僅例子符合ModernCMake,并且每個步驟都會有詳細的注釋來解釋“是什么,為什么”。

例如第一節的HelloCMake,只有短短的幾行:

#SettheminimumversionofCMakethatcanbeused

#Tofindthecmakeversionrun

#$cmake--version

cmake_minimum_required(VERSION3.5)

#Settheprojectname

project(hello_cmake)

#Addanexecutable

add_executable(hello_cmakemain.cpp)

而StaticLibrary一節,也只包含了最核心的內容:

cmake_minimum_required(VERSION3.5)

project(hello_library)

############################################################

#Createalibrary

############################################################

#Generatethestaticlibraryfromthelibrarysources

add_library(hello_librarySTATIC

src/Hello.cpp

)

target_include_directories(hello_library

PUBLIC

${PROJECT_SOURCE_DIR}/include

)

############################################################

#Createanexecutable

############################################################

#Addanexecutablewiththeabovesources

add_executable(hello_binary

src/main.cpp

)

#linkthenewhello_librarytargetwiththehello_binarytarget

target_link_libraries(hello_binary

PRIVATE

hello_library

)

考慮到我給這個項目也提過PR,這里也算有私心吧XD。

而之所以先看01和02是因為這兩個目錄里的內容已經涵蓋了至少80%的使用場景;一下學太多很容易出現遭遇知識洪水的無力感而早早放棄。

對于入門學習來說,知識是螺旋上升的;同時照著優秀的例子learningbydoing可以很好緩解恐懼感。這里算是給藍色的回答提供教材。

EffectiveModernCMake這里的作用類似于C++那幾本Effective。

0x01緊跟步伐&拓展

前面講過,CMake目前正處于現代化運動當中,新版本的迭代也非常快(最新版已經是v3.16了,并且已經內建支持了PCH),因此有一些之前認為是modernpractice的做法可能在后續的版本已經顯得不那么好了。(別緊張,前面說過知識是螺旋式上升的)

所以如果你還想在這個方面有所深入,最好的方式就看各種會議的talk,包括他們的slides。

這里個人比較推薦的幾個有:

EffectiveCMake:arandomseletionofbestpractices--DanielPfeifer

EmbracingModernCMake:HowtorecognizeandusemodernCMakeinterfaces--StephenKellyATDublinC++Meetup

ModernCMakeformodulardesign--MathieuRopertATCppCon-2017

MoreModernCMake:WorkingWithCMake3.12AndLater--DenizBahadirATMeetingC++2018

對應的slides和演講的視頻都可以搜到。

建議:不要試圖一次全看懂,遇到不理解或者不認可的可以先跳過

如果你發現上面的幾個slides的推薦做法有沖突也別緊張,說不定就是moremodern對modern的一次修正呢。

這里順帶舉個例子來說明一下moderncmake發展的有多快。

因為CMake的變量很容易泄露到其他作用域去,所以ModernCMake有一個慣用法就是AvoidUnnecessaryVariables。對于項目的源文件,不依賴變量直接加到target上,同時可以通過generatorexpression設置不同平臺的文件:

add_executable(hello_cmakemain.cpp)

target_source(hello_cmake

PRIVATE

foo.h

foo.cpp

$<$<BOOL:${WIN32}>:

#forWindows

>

$<$<NOT:$<BOOL:${WIN32}>>:

#forPOSIX

>

)

在v3.11之前,add_xxx()定義一個target時,一定要有一個文件(sourceparameter),但是自v3.11開始這個約束被去掉了。所有源碼文件可以通過target_source()引入,避免出現創建library時有一個源碼文件孤零零的放在add_library()中顯得很不協調。

0x02第三方依賴引入

如何引入&管理第三方依賴是一個時常能夠在C++社區引發廣泛討論的話題。

眾所周知,迄今為止C++至少有89種構建系統以及至少64種依賴管理方案,這還是建立在連module都沒有情況下。

ModernCMake下引入第三方依賴目前整體上主要有兩種方式。

第一種是Install&FindPackage

安裝可以有多種途徑,包括不僅限于:Linux系統的各包管理器;vcpkg或者conan這樣單獨包管理器;甚至自己cmakebuild&install。

安裝好第三方庫之后就可以在CMake種使用find_package()引入依賴。

好處是,CMake編寫方便,以及可以使用不支持CMake的第三方庫

但是這種方式的缺點也很明顯:操作復雜度和二進制模塊的ABI問題。

注:headeronly的庫也可以安裝,但是不影響以下討論。

操作復雜度:

使用系統包管理器安裝的庫版本都比較老,想要新的且指定版本的庫需要費工夫

vcpkg不支持庫版本指定,一不小心所有依賴都更新了;想一想沒有gomod甚至沒有vendor機制前的gopackage

conan倒是支持版本控制,庫更新的也勤快,并且可以針對項目單獨指定依賴;但是庫少是真的,并且對CMake使用上是侵入式的

另外一個蛋疼的是ABI。如果你安裝的依賴庫是希望被不同的項目直接使用,那么你遲早會掉到這個坑里。

在Windows上使用MSVC作為編譯器的話,閉著眼睛都能發現:

Debug和Releasebuild是無法兼容鏈接在一起的

/MT和/MD是無法鏈接在一起的

X86和X64是無法鏈接在一起的

甚至有時候不同minor版本的構建也是無法鏈接在一起的(官方保證ABI但是幫同事解決鏈接問題時又遇到)

那么請問你應該安裝的二進制是哪個配伍的呢?

Linux上坑稍微少一點,但是如果庫作者自己不注意,或者安裝的時候flags手抖了,也容易出現問題。

哦,注意你的GCC是不是開了CXX_11_ABI....

當然你也可以像vcpkg一樣把允許所有的組合下二進制都構建安裝一遍...

但是這里還有一個坑:多個ABI版本的二進制庫如果要共存,需要庫作者仔細謹慎的編寫Install模塊!

前面推薦的slides里有不少關于如何正確編寫Export&Install的內容;以及,你現在可以把cmake-examples里的例子看完了:-)。

如果依賴不怎么經常變化的話,通過dockerimage把第三方包都裝好,感覺上可能會比較省事?

第二種方式是源碼依賴。

源碼依賴的意思是說,你可以訪問依賴的完整源代碼,因此構建的時候是第三方依賴先構建,然后再構建你的工程。

注意,源碼依賴模式下,第三方依賴一樣也可以是靜態庫、動態庫。

優點是,你可以精細控制整個構建過程;因為工具鏈&參數是統一的,所以沒有ABI的問題。

缺點有如下幾個:

構建時間長,因為第三方依賴也要構建;同時不同的項目如果依賴同一個庫,需要分別構建。

需要依賴庫支持CMake,或者有人為依賴庫提供好CMake工程描述

源碼依賴在CMake中通過add_subdirectory()添加依賴源碼文件夾實現。

也可以通過ExternalProjectAdd以及v3.11開始提供的FetchContentModule來完成自動化。

Google是源碼依賴的擁躉,他們開源的abseil-cpp、grpc-cpp等都推薦使用源碼依賴的方式進行構建。

研究過Chromium的人想必這輩子都忘不了depot_tools和gclient....

這里單獨提一下FetchContentModule。

這個模塊是v3.11開始有的,并且在v3.14得到了進一步完善。它的核心功能是幫你從指定的VCS地址(比如gitrepo,SVNrepo)或者URL下載依賴,并自動通過add_subdirectory()進入你的工程。

并且這一切發生在configurationstage。

grpc-cpp的官方文檔就提供了使用FetchContent來引入的例子:

include(FetchContent)

FetchContent_Declare(

gRPC

GIT_REPOSITORYhttps://github.com/grpc/grpc

GIT_TAGv1.25.0

)

FetchContent_MakeAvailable(gRPC)

add_executable(my_exemy_exe.cc)

target_link_libraries(my_exegrpc++)

如果你決定使用FetchContent,不妨考慮一下CPM這個CMake擴展。

CPM在FetchContent和傳統的Packagedependency的基礎之上做了很多整合,支持:

指定一個全局的三方源碼依賴緩存文件夾,避免多個項目重復拉取同一個版本的依賴源碼

通過參數fallback到find_package()的方式使用localpackage。

依賴的options控制

最后,希望能在有生之年看到defactopackagemanager出現的那天。。