第91章:使用Conan:集成Conan包管理器
说实话,C++的包管理一直是个让人头疼的问题。Python有pip,JavaScript有npm,Java有maven,而我们C++开发者呢?要么手动下载源码编译,要么写一堆find_package脚本。直到Conan出现,这个局面才真正改观。
我个人是从Conan 1.x时代就开始用了。那时候功能还没现在这么完善,但已经能解决我80%的依赖管理问题。到了Conan 2.x,嗯,可以说真正成熟了。今天我们就来聊聊,怎么在CMake项目中集成Conan。
Conan是什么?
Conan是一个去中心化的C/C++包管理器。说白了,它帮你做三件事:
- 下载依赖:从远程仓库拉取第三方库
- 编译依赖:根据你的编译器、架构、配置(Debug/Release)自动编译
- 集成到CMake:生成CMake可用的配置文件,让你直接用find_package
我在项目中遇到过最典型的场景:团队里有人用VS2022,有人用Clang,还有人用GCC。每个库都要各自编译一遍,版本还经常对不上。用了Conan之后,一个conanfile.txt就搞定了所有。
核心概念速览
先看一张图,帮你快速理解Conan的工作流程:
实战:从零开始集成Conan
我们用一个真实项目来演示。假设你要写一个日志工具,依赖fmt和spdlog。传统做法是手动下载源码,然后add_subdirectory。用Conan呢?三步走。
第一步:写conanfile.txt
在项目根目录创建这个文件:
[requires]
fmt/10.1.1
spdlog/1.12.0
[generators]
CMakeDeps
CMakeToolchain
[layout]
cmake_layout
这里我解释一下:
- requires:声明你要用哪些库,版本号要写清楚。Conan会去远程仓库找对应的包。
- generators:告诉Conan生成什么类型的CMake集成文件。CMakeDeps生成find_package需要的配置文件,CMakeToolchain生成编译器设置。
- layout:指定项目目录结构。cmake_layout是Conan 2.x推荐的布局方式。
conan search 库名 来查。我个人习惯先在ConanCenter(conan.io/center)上搜一下,确认版本号再写。
第二步:编写CMakeLists.txt
这是集成后的CMake文件:
cmake_minimum_required(VERSION 3.24)
project(MyLogger VERSION 1.0.0 LANGUAGES CXX)
# 设置C++标准
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# 查找Conan生成的依赖
find_package(fmt REQUIRED)
find_package(spdlog REQUIRED)
# 添加可执行文件
add_executable(my_logger main.cpp)
# 链接库
target_link_libraries(my_logger
PRIVATE
fmt::fmt
spdlog::spdlog
)
注意这里没有add_subdirectory,也没有手动设置include目录。Conan生成的CMakeDeps文件已经帮你做好了所有路径配置。
第三步:构建项目
构建命令和传统方式略有不同:
# 1. 安装依赖(只需要执行一次)
conan install . --build=missing
# 2. 配置CMake(使用Conan生成的toolchain)
cmake --preset conan-default
# 3. 编译
cmake --build --preset conan-release
为什么会多一个conan install步骤?因为Conan要先下载并编译依赖,生成CMake能用的配置文件。--build=missing的意思是:如果本地没有预编译好的二进制包,就自动从源码编译。
conan install。我曾经因为这个踩过坑——换了编译器没重新install,结果链接了一堆不兼容的库,编译报错找了半天。
Conan 2.x vs 1.x:关键变化
如果你之前用过Conan 1.x,下面这个表格能帮你快速了解2.x的变化:
| 特性 | Conan 1.x | Conan 2.x |
|---|---|---|
| 生成器 | cmake(生成conanbuildinfo.cmake) | CMakeDeps + CMakeToolchain |
| 配置文件 | conaninfo.txt | conaninfo.txt + CMake presets |
| 构建方式 | 手动指定toolchain文件 | cmake --preset 自动加载 |
| 包格式 | 旧格式(兼容性差) | 新格式(更小更快) |
| 推荐度 | 不再推荐新项目使用 | 强烈推荐 |
我个人建议:新项目直接上Conan 2.x。如果你在维护老项目,可以逐步迁移,但别拖太久——Conan 1.x已经进入维护模式了。
避坑指南
用Conan这几年,我踩过不少坑。挑几个典型的说说:
- 版本冲突:两个库依赖了同一个库的不同版本。比如库A要fmt 9.x,库B要fmt 10.x。Conan会报错。解决办法是升级或降级其中一个库,让它们统一版本。
- 二进制兼容性:用MSVC编译的库,不能链接到MinGW的项目里。Conan会按settings区分,但如果你手动改了settings,就可能出问题。
- 缓存问题:有时候改了conanfile.txt,但Conan用了缓存里的旧包。加个--update参数可以强制刷新。
核心要点:
- Conan解决的是C++依赖管理的痛点——自动下载、编译、集成
- conanfile.txt声明依赖,CMakeDeps生成CMake集成文件
- 构建流程:conan install → cmake --preset → cmake --build
- 新项目用Conan 2.x,老项目逐步迁移
好了,关于Conan集成就聊这么多。说白了,它就是给C++项目装了个包管理器,让依赖管理变得像Python一样简单。你想想看,以前手动编译第三方库要花多少时间?现在一个conan install就搞定了,省下来的时间干点啥不好?