在进行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
状况进行配置。