关于cmake:CMake使用入门

33次阅读

共计 3869 个字符,预计需要花费 10 分钟才能阅读完成。

在进行 C ++ 时,抉择什么样的编译器显得十分的重要。与其它的语言不同,C++ 的程序最终由头文件 (.h) 以及库文件 (.dll 或.so) 组件。
不同的利用(库)帮助工作时,同样须要对文件及库文件的反对,而不同的平台上的库文件是不统一的,所以在跨平台的开发中,咱们更喜爱应用 cmake 来进行编译链接。

所以 cmake 并不是包管理工具,他并不可能解决包的依赖问题,而仅仅解决的跨平台的问题。

编译器

将源代码变成可执行的利用须要一个叫做编译器的货色,如果在利用中应用了曾经成型的第三方库,或是本人的利用较大,须要多个模块配合的话。还须要将这些模仿连接起来,最终造成一个能够应用的应用程序。

就这像在一个规范的 Spring boot 我的项目在构建时,可能构建出一个蕴含本人和其它第三方库,可被间接运行的 xxx.jar 和一个只蕴含本人的可被用做第三方库的 xxx.jar.original 文件。

而将源代码变成可执行的字节码的过程叫做编译,将源代码本人生成的库与其它库连在一起,最初造成可执行应用程序的过程则叫做链接。

实现上述性能的工具则称为编译器。

在 java 开发中,咱们须要针对不同的操作系统下载不同的 jdk。这个 jdk 中有一部分的作用便是 java 的编译器。在 C ++ 开发中,macos 中曾经默认装置了一款名为 clang 的编译器,所以咱们并不需要独自的装置它。

须要叫各个系统中 c ++ 的编译器不同,比方 macos 中默认装置的是 clang。除此以外,编译器还有注明的 GNU(gcc、g++)。而不同的编译器均领有本人的特点,咱们在开发利用时,也会将这些编译器的特点退出到咱们的源代码中。而后编译器在依据源代码来编译为字节文件。在有些个性只有特定的编译器才反对,这也是为什么有的利用只能应用特定编译器编译能力工作的起因。

依赖治理

java 中有比拟驰名的 mavengradle 包管理器,它可能主动的为咱们下载依赖,接着调用指定的 jdk 进行编译,可能实现 java 利用的打包工作。

不太侥幸的是 c ++ 利用中并没有这么弱小的包管理工具。但一个多模块有依赖的我的项目,实现的思维依然是雷同的。

如同 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 中:

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

正文完
 0