CMake使用入門

在進行C++時,選擇什麼樣的編譯器顯得很是的重要。與其它的語言不一樣,C++的程序最終由頭文件(.h)以及庫文件(.dll或.so)組件。
不一樣的應用(庫)協助工做時,一樣須要對文件及庫文件的支持,而不一樣的平臺上的庫文件是不一致的,因此在跨平臺的開發中,咱們更喜歡使用cmake來進行編譯連接。java

因此cmake並非包管理工具,他並不可以解決包的依賴問題,而僅僅解決的跨平臺的問題。c++

編譯器

將源代碼變成可執行的應用須要一個叫作編譯器的東西,若是在應用中使用了已經成型的第三方庫,或是本身的應用較大,須要多個模塊配合的話。還須要將這些模擬鏈接起來,最終造成一個可使用的應用程序。git

就這像在一個標準的Spring boot項目在構建時,可以構建出一個包含本身和其它第三方庫,可被直接運行的xxx.jar和一個只包含本身的可被用作第三方庫的xxx.jar.original文件。github

而將源代碼變成可執行的字節碼的過程叫作編譯,將源代碼本身生成的庫與其它庫連在一塊兒,最後造成可執行應用程序的過程則叫作連接。shell

完成上述功能的工具則稱爲編譯器。macos

在java開發中,咱們須要針對不一樣的操做系統下載不一樣的jdk。這個jdk中有一部分的做用即是java的編譯器。在C++開發中,macos中已經默認安裝了一款名爲clang的編譯器,因此咱們並不須要單獨的安裝它。npm

須要叫各個系統中c++的編譯器不一樣,好比macos中默認安裝的是clang。除此之外,編譯器還有註明的GNU(gcc、g++)。而不一樣的編譯器均擁有本身的特色,咱們在開發應用時,也會將這些編譯器的特色加入到咱們的源代碼中。而後編譯器在根據源代碼來編譯爲字節文件。在有些特性只有特定的編譯器才支持,這也是爲何有的應用只能使用特定編譯器編譯才能工做的緣由。json

依賴管理

java中有比較著名的mavengradle包管理器,它可以自動的爲咱們下載依賴,接着調用指定的jdk進行編譯,可以完成java應用的打包工做。bootstrap

不太幸運的是c++應用中並無這麼強大的包管理工具。但一個多模塊有依賴的項目,實現的思想仍然是相同的。windows

如同npm下管理的包在package.json中聲明瞭須要的包及版本號,而後使用npm install的命令來安裝。C++的應用則能夠在CMakeLists.txt來聲明版本號。而後使用其它的方式來安裝。

加載依賴

前面講了cmake是一款跨平臺的編譯器,而它對應的配置文件則是CMakeLists.txt,在該文件中說明了對其它第三方包的依賴。

find_package()

CMakeLists.txt聲明依賴的方式大致分爲兩種,第一種是使用find_package
好比:find_package(JsonCpp REQUIRED)。此時CMake會先查找其內部包,若是沒有在內部包中找到,則會在當前目錄下查找文件FindJsonCpp.cmake文件。若是找到了FindJsonCpp.cmake文件,則會按該文件的設置加載包;若是沒有找到,因爲第二個參數設置的值爲REQUIRED,則會拋出一個異常。

因此若是某些第三方包提供了FindXxxx.cmake文件的話,能夠輕鬆的使用find_package(name, REQUIRED)函數來加載第三方包。

通常狀況下,如成功的找到第三方包將會定義以下變量:

# 找到包時,該值爲true
Xxxx_FOUND
# 該包頭文件所在位置
Xxxx_INCLUDE_DIRS 或 Xxxx_INCLUDES
# 該包庫文件所在位置
Xxxx_LIBRARY 或 Xxxx_LIBRARIES 或 Xxxx_LIBS
# 可使用message(${Xxxx_LIBRARIES})來打印變量的值

pkg_check_modules()

第二種方式是藉助於PkgConfig

find_package(PkgConfig REQUIRED)

當系統未安裝PkgConfig則會提到一個未找到PkgConfig的錯誤,此時則須要在系統中安裝PkgConfig

有了PkgConfig後即可以使用其提供的pkg_check_modules包檢測方法來獲取第三方包的信息了:

pkg_check_modules(JSONCPP jsoncpp)

其中JSONCPP爲別名能夠隨便起,jsoncpp爲模塊名。

此時當存在jsoncpp時,則系統變量JSONCPP__FOUND的值爲true,不然爲false。若是當前項目必須依賴於某個第三方包,則能夠加入REQUIRED,好比:pkg_check_modules(XXX xxx REQUIRED)此時當不存在xxx時將會發生一個異常。

加載

不管是經過find_package()仍是經過pkg_check_modules來獲取第三方依賴包,其本質上都是在:檢查是否存在某個包,若是存在則返回該包的信息,若是不存在,則將系統變量Xxxx_FOUND設置爲false。除此之外,並無其它做用。

也就是說上述兩個方法並無加載對其第三方的依賴。這因此要使用命令來查找某個包的信息(包的庫文件、頭文件位置),也是考慮了跨平臺的緣由。在跨平臺的狀況下,咱們不能使用諸如windows中的c:\xxx\xxx或xunix中的~/xxx/xxx任一形式。因此在加載某個依賴前,須要經過上述方法來動態獲取包的信息,若是當前使用的是windows系統,則能夠是c:\xxx\xx的形式,若是使用的是xunix系統,則多是/usr/local/xxx的形式。

加載第三方庫須要將頭文件使在位置使用include_directories包含進來,並將庫使用target_link_libraries連接進來。

include_directories(project-name ${Xxxxx_INCLUDE_DIRS})
target_link_libraries(project-name ${Xxxxx_LIBRARIES})

包管理器

Microsoft提供了vcpkg來安裝c++應用的依賴。使用shell安裝方式以下:

# clone倉庫
git clone https://github.com/Microsoft/vcpkg.git --depth=1
# 進入倉庫
cd vcpkg
# 運行安裝腳本
./bootstrap-vcpkg.sh
# 設置爲全局安裝,之後再安裝其它包的時候,都是全局的
./vcpkg integrate install

執行徹底局安裝後,將會獲得一個提示:

panjie@panjies-iMac vcpkg % ./vcpkg integrate install
Applied user-wide integration for this vcpkg root.

CMake projects should use: "-DCMAKE_TOOLCHAIN_FILE=/Users/panjie/github/Microsoft/vcpkg/scripts/buildsystems/vcpkg.cmake"

它在說若是咱們再使用CMake工具的話,則須要在CMake命令後追加上述參數。若是咱們使用了Clion編輯器,則須要將其添加到CMake options中:
image.png
此時Clion中的Cmake則會在執行時自動加入上述參數。自此之後Clion即可以和cmake及vcpkg包管理器愉快的工做在一塊兒了。

安裝特定的包

好比咱們安裝一個用於json序列化的jsoncpp,則能夠在vcpkg中執行:./vcpkg install jsoncpp

panjie@panjies-iMac vcpkg % ./vcpkg install jsoncpp       
Computing installation plan...
...
The package jsoncpp:x64-osx provides CMake targets:

    find_package(jsoncpp CONFIG REQUIRED)
    target_link_libraries(main PRIVATE jsoncpp_object jsoncpp_static)

最後按照提示將上述代碼添加到本身項目中的CMakeLists.txt中,而後即可以愉快的在項目中使用第三方jsoncpp包了:

add_executable(yz-main yz-main.cpp)
    find_package(jsoncpp CONFIG REQUIRED)
    target_link_libraries(yz-main PRIVATE jsoncpp_object jsoncpp_static)

此後即可以在當前工程中自由的使用jsoncpp來完成json的序列化與反序列化工做了。

總結

最後使用java與c++項目作對比總結:

  1. 二者都屬於編譯型語言,都須要先編譯。
  2. java源文件使用jdk來編譯,不一樣的操做系統須要安裝不一樣的JDK安裝包;C++須要使用C++編譯器進行編譯,不一樣的操做系統須要下載不一樣的編譯器。
  3. java的編譯器有多個版本,好比oracle自家的jdk,或是第三方的openjdk;C++的編譯器也有多個版本,好比clang、GNU。在實際的開發過程當中,須要按本身的需求進行下載、安裝配置。
  4. java中有統一的包管理、安裝工具mavengradle;C++有統一的包管理工具vcpkg,有統一的安裝工具cmake
  5. vcpkg想與cmake愉快的工做,須要配置一些參數。該參數不一樣的計算機會有不一樣,須要按安裝vcpkg狀況進行配置。
相關文章
相關標籤/搜索