在進行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中有比較著名的maven
、gradle
包管理器,它可以自動的爲咱們下載依賴,接着調用指定的jdk進行編譯,可以完成java應用的打包工做。bootstrap
不太幸運的是c++應用中並無這麼強大的包管理工具。但一個多模塊有依賴的項目,實現的思想仍然是相同的。windows
如同npm
下管理的包在package.json
中聲明瞭須要的包及版本號,而後使用npm install
的命令來安裝。C++的應用則能夠在CMakeLists.txt
來聲明版本號。而後使用其它的方式來安裝。
前面講了cmake是一款跨平臺的編譯器,而它對應的配置文件則是CMakeLists.txt
,在該文件中說明了對其它第三方包的依賴。
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})來打印變量的值
第二種方式是藉助於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中:
此時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++項目作對比總結:
maven
或gradle
;C++有統一的包管理工具vcpkg
,有統一的安裝工具cmake
。vcpkg
想與cmake
愉快的工做,須要配置一些參數。該參數不一樣的計算機會有不一樣,須要按安裝vcpkg
狀況進行配置。