Sorry, your browser cannot access this site
This page requires browser support (enable) JavaScript
Learn more >

1. 历史背景与发展历程

Conan是由JFrog公司(以Artifactory二进制仓库管理工具闻名)于2016年推出的开源、跨平台C/C++包管理器。

  • 发展背景:C/C++生态长期缺乏统一包管理方案,传统手动方式效率低且依赖关系复杂,不同平台、编译器和配置组合使依赖管理困难。
  • 发展历程
    • 2016年:Conan 0.1版本发布,基于Python编写,采用客户端 - 服务器架构。
    • 2017年:Conan 1.0正式发布,引入完善配方(recipe)系统和二进制兼容性管理。
    • 2019年:ConanCenter成为社区共享包的中心仓库,丰富了可用包。
    • 2021年:Conan 2.0开始开发,引入重大架构改进。
    • 2023年:Conan 2.0正式发布,改进依赖解析算法、简化配置文件、增强锁文件功能。

2. conan安装

2.1. 通过pip或pipx安装

Conan工具本身是Python开发的,所以可以通过pip或pipx来安装。

2.1.1. pip 安装

1
2
3
4
5
6
7
8
9
10
11
# 创建虚拟环境
python3 -m venv ~/conan_env

# 激活环境
source ~/conan_env/bin/activate

# 安装 conan
pip install conan

# 使用完毕后可退出环境
deactivate

说明:

  • Ubuntu 23.04+、Debian 12+之后增加了PEP 668保护机制,为了防止破坏系统的Python环境,需要在虚拟环境下安装。
  • 每次使用 conan 需要先激活环境

2.1.2. pipx 安装(推荐)

1
2
3
4
5
6
7
8
9
# 安装 pipx(如果未安装)
sudo apt install pipx
pipx ensurepath

# 安装 conan
pipx install conan

# 验证
conan --version

2.1.3. pipx 与 pip 的区别

特性 pip pipx
用途 安装 Python 包(库、框架、工具) 专门安装和运行 Python 应用(命令行工具)
安装方式 直接安装到 Python 环境 每个工具独立隔离的虚拟环境
依赖管理 所有包共享同一环境(可能冲突) 每个工具独立环境,依赖隔离
主要使用场景 开发 Python 项目时安装依赖库 安装 Python 编写的命令行工具(如 conan, black, pytest)
命令执行 需要手动添加到 PATH 或激活环境 自动将命令链接到 PATH,直接可用
卸载 可能遗留依赖,影响其他包 完整卸载,不影响其他工具

2.2. 通过平台默认的包管理器安装

2.2.1. Ubuntu/Debian

1
2
3
4
5
6
7
# 更新系统包
sudo apt update
sudo apt upgrade
# 安装conan
sudo apt install conan
# 验证安装是否成功
conan --version

2.2.2. macOS

1
2
3
4
5
6
# 安装brew
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
# 安装conan
brew install conan
# 验证安装是否成功
conan --version

2.2.3. Windows

1
2
3
4
# 安装conan
choco install conan
# 验证安装是否成功
conan --version

说明: Chocolatey(choco)是Windows平台的命令行包管理器,类似于Ubuntu的apt或macOS的Homebrew。

3. 核心功能

3.1. 依赖管理

  • 自动下载和安装 C/C++ 库依赖
  • 处理依赖关系树和版本冲突
  • 支持传递依赖(依赖的依赖)

3.2. 多平台支持

  • 操作系统:Windows, Linux, macOS, Android, iOS
  • 编译器:GCC, Clang, MSVC, MinGW
  • CPU架构:x86, x86_64, ARM, ARM64

3.3. 二进制包管理

  • 预编译二进制包,避免源码重复编译
  • 通过设置(settings)区分不同平台、编译器、构建类型、架构等。
  • 支持二进制兼容性检测,自动匹配可用的预编译包。
  • 本地缓存机制,加速构建

3.4. 可与多种构建系统集成

  • CMake(最常用)
  • Visual Studio (MSBuild)
  • Makefiles, Autotools
  • Meson, Bazel, etc.

3.5. 多仓库支持

  • 支持多个远程仓库,可混合使用公共仓库(ConanCenter)和私有仓库。
  • 支持JFrog Artifactory、GitLab、自建服务器等作为仓库后端。

3.6. 依赖解析与版本管理

  • 支持语义化版本(semver)约束,如pkg/[>=1.0 <2.0]
  • 支持多种依赖类型:requirestool_requires(构建工具依赖)、test_requires
  • 提供锁文件(lockfile)机制,确保可重现的依赖版本。

3.7. 可扩展的配方系统

  • 使用Python编写包配方(conanfile.py),可定制包的构建、打包、依赖逻辑。
  • 支持生成多种构建系统集成文件(如CMake的conan_toolchain.cmakeconanbuildinfo.cmake)。

3.8. 虚拟环境管理

  • 可创建虚拟运行环境,自动设置PATH、LD_LIBRARY_PATH等环境变量。
  • 支持虚拟构建环境,隔离构建工具链。

4. 架构与核心概念

4.1. 核心组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
┌─────────────────────────────────────────────┐
│ Conan 生态系统 │
├─────────────────────────────────────────────┤
│ │
│ ┌──────────┐ ┌──────────────┐ │
│ │ Client │────▶│ Remote │ │
│ │ (conan) │ │ Repositories│ │
│ └────┬─────┘ └──────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────┐ ┌──────────────┐ │
│ │ Local │ │ Profiles │ │
│ │ Cache │ │ │ │
│ └──────────┘ └──────────────┘ │
│ │
│ ┌──────────-┐ ┌──────────────┐ │
│ │ Recipes │ │ Generators │ │
│ │(conanfile)│ │ │ │
│ └──────────-┘ └──────────────┘ │
└─────────────────────────────────────────────┘

4.2. 重要概念详解

概念 说明 示例
Recipe(配方) 定义如何获取、构建、打包库 conanfile.py
Profile(配置) 定义编译环境设置 编译器版本、架构、构建类型
Package(包) 特定配置下构建的二进制文件 openssl/1.1.1
Reference(引用) 包的完整标识 zlib/1.2.11@conan/stable
Revision(修订版) 配方或包的版本 da39a3ee5e6b4b0d
Channel(通道) 包的质量标识 stable, testing

5. Conan 文件详解

5.1. conanfile.txt(简单项目)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[requires]
# 依赖包列表
fmt/10.1.0
spdlog/1.12.0
openssl/3.0.0

[options]
# 包选项
fmt:shared=True # 使用动态库
openssl:openssl_rand=True

[generators]
# 生成器列表
CMakeDeps # 生成 CMake 依赖文件
CMakeToolchain # 生成 CMake toolchain
VirtualBuildEnv # 设置构建环境

[imports]
# 复制文件到项目
bin, *.dll -> ./bin # 复制 DLL 到 bin 目录
lib, *.dylib -> ./lib # 复制动态库

5.2. conanfile.py(高级/创建包)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
from conan import ConanFile
from conan.tools.cmake import CMake, CMakeToolchain, cmake_layout
from conan.tools.files import copy, get
import os

class MyLibraryConan(ConanFile):
# 基本信息
name = "mylibrary"
version = "1.0.0"
description = "My awesome C++ library"
url = "https://github.com/myuser/mylibrary"
license = "MIT"

# 依赖
requires = "fmt/10.1.0"

# 设置
settings = "os", "compiler", "build_type", "arch"

# 选项
options = {
"shared": [True, False],
"fPIC": [True, False]
}
default_options = {
"shared": False,
"fPIC": True
}

# 源码导出
exports_sources = "CMakeLists.txt", "src/*", "include/*"

def layout(self):
# 定义目录布局
cmake_layout(self)

def generate(self):
# 生成构建文件
tc = CMakeToolchain(self)
tc.variables["MY_LIBRARY_VERSION"] = self.version
tc.generate()

def build(self):
# 构建库
cmake = CMake(self)
cmake.configure()
cmake.build()

def package(self):
# 打包文件
cmake = CMake(self)
cmake.install()

# 复制 license
copy(self, "LICENSE", src=self.source_folder,
dst=os.path.join(self.package_folder, "licenses"))

def package_info(self):
# 设置包信息
self.cpp_info.libs = ["mylibrary"]
self.cpp_info.includedirs = ["include"]
self.cpp_info.libdirs = ["lib"]

# 设置依赖信息
if self.options.shared:
self.cpp_info.defines.append("MYLIBRARY_SHARED")

5.3. Profile 文件示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# default profile (Linux)
[settings]
os=Linux
os_build=Linux
arch=x86_64
arch_build=x86_64
compiler=gcc
compiler.version=11
compiler.libcxx=libstdc++11
build_type=Release

[options]
# 全局选项
*:shared=False

[conf]
# 工具配置
tools.cmake.cmaketoolchain:generator=Ninja
tools.build:compiler_executables={"cxx": "/usr/bin/g++-11"}

[buildenv]
# 环境变量
CC=/usr/bin/gcc-11
CXX=/usr/bin/g++-11

6. 常用命令详解

6.1. 包管理命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 搜索包
conan search "boost*" --remote=conancenter
conan search zlib/1.2.11@

# 查看包信息
conan inspect zlib/1.2.11
conan get zlib/1.2.11 conanfile.py

# 下载包(不构建)
conan download fmt/10.1.0

# 查看本地缓存
conan list
conan cache path fmt/10.1.0

# 删除包
conan remove fmt/10.1.0
conan remove "*" # 删除所有(谨慎)

6.2. 构建命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 安装依赖
conan install . --build=missing
conan install . -s build_type=Debug -s arch=x86_64

# 构建包
conan build .

# 创建包(构建+打包)
conan create . user/channel
conan create . --build=missing -s build_type=Release

# 导出包到本地
conan export . user/channel

# 上传包
conan upload mylibrary/1.0.0 --remote=myremote

6.3. 配置管理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# Profile 管理
conan profile detect # 自动检测
conan profile list # 列出所有
conan profile show default # 显示内容
conan profile new myprofile --detect # 创建新配置
conan profile update settings.compiler=gcc myprofile

# 远程仓库管理
conan remote list # 列出远程仓库
conan remote add myrepo https://myrepo.com
conan remote remove myrepo
conan remote update myrepo https://newurl.com

# 配置管理
conan config home # 显示配置目录
conan config install <url> # 安装配置

6.4. 依赖图分析

1
2
3
4
5
6
7
8
9
# 生成依赖图
conan graph info . --format=html > deps.html
conan graph info . --format=dot > deps.dot

# 查看依赖树
conan graph info . --graph=graph.html

# 检查冲突
conan graph info . --build=missing

7. 与 CMake 集成详解

7.1. 项目结构

1
2
3
4
5
6
7
myproject/
├── CMakeLists.txt
├── conanfile.txt
├── build/
│ └── (conan install 在这里运行)
└── src/
└── main.cpp

7.2. CMakeLists.txt 配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
cmake_minimum_required(VERSION 3.15)
project(MyProject CXX)

# 设置 C++ 标准
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# 查找 Conan 生成的包
find_package(fmt REQUIRED)
find_package(spdlog REQUIRED)
find_package(OpenSSL REQUIRED)

# 创建可执行文件
add_executable(myapp src/main.cpp)

# 链接依赖
target_link_libraries(myapp
PRIVATE
fmt::fmt
spdlog::spdlog
OpenSSL::SSL
OpenSSL::Crypto
)

# 设置属性
target_compile_features(myapp PRIVATE cxx_std_17)

7.3. 构建流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 方式1:手动构建
mkdir build && cd build
conan install .. --build=missing
cmake .. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake
cmake --build . --config Release

# 方式2:使用 conan 构建
conan install . --build=missing
conan build .

# 方式3:使用预设(CMakePresets.json)
conan install . --build=missing
cmake --preset conan-default
cmake --build --preset conan-default

7.4. 多配置构建

1
2
3
4
5
6
7
8
9
# 构建 Debug 版本
conan install . -s build_type=Debug --build=missing
cmake .. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Debug
cmake --build . --config Debug

# 构建 Release 版本
conan install . -s build_type=Release --build=missing
cmake .. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Release
cmake --build . --config Release

8. 高级功能

8.1. 版本管理

1
2
3
4
5
6
7
8
9
10
11
12
13
# conanfile.py 中的版本管理
class MyPkg(ConanFile):
# 硬编码版本
version = "1.0.0"

# 从文件读取版本
def set_version(self):
with open("VERSION") as f:
self.version = f.read().strip()

# 使用环境变量
def set_version(self):
self.version = os.getenv("PKG_VERSION", "0.0.0")

8.2. 条件依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
class MyPkg(ConanFile):
requires = "zlib/1.2.11"

# 可选依赖
def requirements(self):
if self.options.with_ssl:
self.requires("openssl/3.0.0")
if self.settings.os == "Windows":
self.requires("winpcap/4.1.3")

options = {
"with_ssl": [True, False]
}

8.3. 测试包

1
2
3
4
5
6
7
8
9
10
11
12
13
# test_package/conanfile.py
from conan import ConanFile
from conan.tools.build import can_run

class TestPackage(ConanFile):
settings = "os", "arch", "compiler", "build_type"

def requirements(self):
self.requires(self.tested_reference_str)

def test(self):
if can_run(self):
self.run("test_package", env="conanrun")
1
2
3
4
5
6
7
8
// test_package/test_package.cpp
#include <mylibrary.h>
#include <iostream>

int main() {
std::cout << "Version: " << mylibrary::version() << std::endl;
return 0;
}

8.4. 锁定文件(Lockfiles)

1
2
3
4
5
6
7
8
# 生成锁定文件(固定所有依赖版本)
conan lock create conanfile.txt --lockfile=conan.lock

# 使用锁定文件安装
conan install . --lockfile=conan.lock

# 更新锁定文件
conan lock create conanfile.txt --lockfile=conan.lock --update

8.5. 工作空间(Workspace)

1
2
3
4
5
6
7
8
9
10
11
12
13
# conanws.yml
workspace:
root: .
settings:
- os
- compiler

packages:
- path: libs/libA
- path: libs/libB
- path: apps/app1

layout: flat

9. 实际应用示例

9.1. 示例1:简单应用使用依赖

conanfile.txt

1
2
3
4
5
6
7
[requires]
fmt/10.1.0
spdlog/1.12.0

[generators]
CMakeDeps
CMakeToolchain

main.cpp

1
2
3
4
5
6
7
8
#include <fmt/core.h>
#include <spdlog/spdlog.h>

int main() {
fmt::print("Hello, {}!\n", "Conan");
spdlog::info("Welcome to Conan");
return 0;
}

构建脚本

1
2
3
4
5
6
#!/bin/bash
mkdir -p build && cd build
conan install .. --build=missing
cmake .. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Release
cmake --build .
./myapp

9.2. 示例2:创建和使用自己的包

创建库

1
2
3
4
5
6
7
8
9
# 创建库项目
mkdir mymath && cd mymath
# 编写 conanfile.py 和源代码
conan create . user/testing

# 使用库
mkdir ../myapp && cd ../myapp
# 在 conanfile.txt 中添加:mymath/1.0.0@user/testing
conan install . --build=missing

9.3. 示例3:交叉编译

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 创建 Android profile
cat > android_profile << EOF
[settings]
os=Android
os.api_level=21
arch=armv8
compiler=clang
compiler.version=14
build_type=Release

[conf]
tools.android:ndk_path=/path/to/android-ndk
EOF

# 使用 profile 构建
conan install . -pr=android_profile --build=missing

10. 最佳实践

10.1. 项目结构建议

1
2
3
4
5
6
7
8
9
10
11
project/
├── conanfile.py # 根目录配方
├── CMakeLists.txt
├── cmake/
│ └── conan_toolchain.cmake
├── src/
│ └── ...
├── test_package/ # 测试包
│ ├── conanfile.py
│ └── test_package.cpp
└── build/ # 构建目录

10.2. 性能优化

1
2
3
4
5
6
7
8
# 使用并行构建
conan install . --build=missing -c tools.build:jobs=8

# 使用 ccache
conan config set tools.build:compiler_cache=ccache

# 使用本地缓存服务器(Artifactory)
conan remote add my_local http://localhost:8081

10.3. 调试技巧

1
2
3
4
5
6
7
8
9
10
11
# 详细输出
conan install . -vvv

# 保留构建目录
conan install . --keep-build

# 查看依赖树
conan graph info . --build=missing

# 检查包配置
conan inspect fmt/10.1.0 -a=settings -a=options

11. 常见问题解决

11.1. 依赖冲突

1
2
3
4
5
6
7
8
9
10
# 使用版本范围
[requires]
boost/[>=1.75 <1.80]

# 覆盖版本
[requires]
openssl/1.1.1
curl/7.84.0
[overrides]
openssl/1.1.1

11.2. 找不到头文件

1
2
3
4
5
6
# CMakeLists.txt 中
find_package(fmt REQUIRED)
target_link_libraries(myapp fmt::fmt)

# 或手动添加
target_include_directories(myapp PRIVATE ${CONAN_INCLUDE_DIRS})

11.3. 符号未定义错误

1
2
3
4
5
# 检查链接顺序
target_link_libraries(myapp PRIVATE libA libB) # 注意依赖顺序

# 检查库类型(静态/动态)
conan install . -o *:shared=True

12. 与其他包管理工具的比较

特性 Conan vcpkg Hunter CMake FetchContent
跨平台
预编译包
自定义包 困难
多版本共存 有限
企业私有仓库 有限
学习曲线 中等

Conan 适用于需要精细控制、多版本管理、企业级私有仓库的场景。对于简单项目,vcpkg 或 FetchContent 可能更简单。

13. 相关文档

C/C++包管理工具vcpkg

评论