9

使用 Conan 管理 C++ 依赖

 3 years ago
source link: https://timothyqiu.com/archives/conan-package-manager/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
使用 Conan 管理 C++ 依赖

现代 CMake 使用 C++ 依赖项时已经相对方便了。比如 find_package(OpenSSL 1.0 REQUIRED) 就可以自动在本地机器上查找已安装的与 OpenSSL 1.0 兼容的包,然后就可以直接 target_link_libraries(targetName PRIVATE OpenSSL::SSL) 使用,不必再手动写头文件和库文件配置。

要做到「本地机器上已安装」,macOS 和 Linux 系统都非常方便,大多数库都可以直接通过系统级包管理工具安装,而 Windows 上就稍显麻烦。我之前比较喜欢的是,比较复杂的库还是留着在各平台手动安装,简单的则使用 CMake 的 FetchContent 模块下载使用。但这样的缺点是每次重新生成工程时,都需要下载一遍依赖并编译。尤其最近国内的网络状态,HTTPS 连接 GitHub 经常超慢。所以想想还是用现成的包管理工具吧。

目前市面上流行的包管理工具中:vcpkg 虽然很多人用,但是微软那套逻辑我始终表示审美不能;Hunter 虽然是纯 CMake 解决方案,但是官方涵盖的库偶有不足;而 Conan 我一开始是不喜欢的,不但需要使用 Python 安装,而且它的前世 biicode 当年也风光过现在已经挂了。不过现在看来,Conan 似乎是这几个之中比较成熟好用的解决方案,至少,符合我的审美就是了。

官方推荐用 Python 在虚拟环境里用 pip install conan 安装,可以随时保持最新。

我在 macOS 上使用 Homebrew 安装,可以少管理一个虚拟环境。感觉 Arch Linux 这样滚动更新的系统也可以直接使用系统包管理工具安装。

找到想要的库

想要使用 spdlog 时,首先搜索:

$ conan search spdlog -r conan-center
Existing package recipes:

spdlog/0.14.0@bincrafters/stable
spdlog/0.16.3@bincrafters/stable
spdlog/0.17.0@bincrafters/stable
spdlog/1.0.0@bincrafters/stable
spdlog/1.1.0@bincrafters/stable
spdlog/1.2.1@bincrafters/stable
spdlog/1.3.0@bincrafters/stable
spdlog/1.3.1@bincrafters/stable
spdlog/1.4.1@bincrafters/stable
spdlog/1.4.2
spdlog/1.4.2@bincrafters/stable
spdlog/1.5.0

命令行中的 -r conan-center 表示所要搜索的仓库,conan-center 是官方自带的默认仓库,如果你本地添加了多个仓库的话,也可以用 all 表示搜索所有仓库。不带这个选项时则是在本地的缓存中查找。

搜索结果中每一行都是一个可用的包的名称,使用 @user/channel 后缀的是完整的包命名方式。官方 conan-center 仓库中,最近的包都是通过 CI 自动构建二进制文件的,这些包使用name/version 的命名方式。

想要知道某个版本/包的详情,可以使用这样的命令查看:

$ conan inspect spdlog/1.5.0

会列出一些信息和安装时的可选参数。

当然,你也可以直接在网站 https://conan.io/center/ 查找 conan-center 仓库中的包。

依赖的指定、安装、使用

一般使用名为 conanfile.txt 的纯文本文件指定依赖,格式类似 INI 文件。

[requires]
spdlog/1.5.0

[generators]
cmake_find_package

[requires] 部分很简单,列出你所需要依赖的包的名称即可。[generators] 部分指定所需要的「生成器」,可以生成与 CMake、SCons 等工具的对接文件。

使用 conan install /path/to/source-dir 可以安装依赖并生成对接文件,参数为包含 conanfile.txt 的目录。当然,这样做会把「对接文件」生成在当前目录,可以使用 -if 参数指定输出目录,推荐放在 CMake 的构建目录。

这样,Conan 就会把 1.5.0 版本的 spdlog 安装到自己管理的目录(一般是 ~/.conan),然后在输出目录输出一个 Findspdlog.cmake 文件。

CMakeLists.txt 中,要让 find_package 使用 Findspdlog.cmake 文件,把它所在的目录加入到 CMAKE_MODULE_PATH 中即可:

# 因为我们把 Findspdlog.cmake 输出到了构建目录
list(APPEND CMAKE_MODULE_PATH "${CMAKE_BINARY_DIR}")

# 按照正常方式搜索
find_package(spdlog REQUIRED)

# ...

# 这个生成器导出的目标是 package::package
target_link_libraries(targetName PRIVATE spdlog::spdlog)

当然,官方教程中使用的是 cmake 生成器,它不会生成 FindXXX.cmake,而是生成一个 conanbuildinfo.cmake,你需要在 CMakeLists.txt 中手动初始化:

include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
conan_basic_setup(TARGETS)

# ...

# 这个生成器导出的目标是 CONAN_PKG::package
target_link_libraries(targetName PRIVATE CONAN_PKG::spdlog)

这种方法把 Conan 显式写入了 CMake 配置里,我个人不是很喜欢。(但是 CONAN_PKG::package 的表述确实比 package::package 好一些,因为一些库官方提供的目标并不都是 package::package。)

Conan 默认安装/构建的二进制是 Release 版本的。而 CMake 的默认构建方式则是 Debug。

所以,尤其在使用类似 MSVC 的编译器时,你可能需要手动指定安装 Debug 版:

$ conan install . -s build_type=Debug

当然你也可以试试 cmake_multi 或者 cmake_find_package_multi 生成器,可以同时安装 Debug 和 Release 版本。抑或是使用官方提供的CMake 集成,自己写脚本把 CMake 和 Conan 的构建类型同步起来。

在使用 conanfile.txt 指定依赖时,还可以同时指定一些可选参数。比如指定使用 spdlog 的动态链接版本:

[options]
spdlog:shared=True

好了,这就是大致的 Conan 使用介绍。

真正上手,还请参阅官方文档 https://docs.conan.io/

C++


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK