c++包管理器conan的使用

木头的喵喵拖孩

前言

原来 c/c++ 也是有包管理器的。

conan

vcpkg 和 conan 是两个 c/c++ 流行的包管理器,我选择 conan 是因为它灵活,不像 vcpkg 非要和微软绑定(我的编译器也是采用的 MinGW,不喜欢微软的编译器)

安装 python

conan 依赖 pip,所以需要先安装 python。
python 安装过于简单,此处略。
需要注意的是,conan 部分功能依赖于 python,需要考虑安装合适的 python 版本。

切换 pip 源

pip 默认源在国内访问速度很慢,可以切换为国内源。

1
2
# 如果pip的可执行文件又被更改过文件名,需要使用更改后的文件名,比如当pip.exe改为pip3.exe时,需要使用pip3
pip config set global.index-url https://mirrors.aliyun.com/pypi/simple/

切换完成后,可以使用下面命令检测是否切换成功。

1
pip config list

安装 conan

1
pip install conan

检测 conan 是否安装成功

1
conan --version

配置第三方库默认安装目录

conan 会默认在当前用户目录(C 盘)下安装第三方库,可以通过修改 global.conf 文件来修改默认安装目录。
找到 global.conf 文件,一般在当前用户目录下的 .conan2 目录中可以找到。添加如下内容。

1
core.cache:storage_path = C:\Users\danielm\my_conan_storage_folder

core.cache:storage_path

Absolute path to a folder where the Conan packages and the database of the packages will be stored. This folder will be the heaviest Conan storage folder, as it stores the binary packages downloaded or created.

安装 meson(可选)

1
2
3
4
pip install meson

# 检测是否安装成功
meson --version

安装 ninja(可选)

https://github.com/ninja-build/ninja/releases

安装 nasm(可选)

https://www.nasm.us/

搜索远程仓库

1
2
# 例如需要搜索jsoncpp的包,不加 -r 表示搜索本地仓库
conan search jsoncpp -r conancenter

Demo

项目目录结构如下:

  • conanfile.txt
  • CMakeLists.txt
  • src/
    • main.cpp
  • build/

conanfile.txt

conanfile.txt 是 conan 在本项目下的配置文件,描述项目所需的依赖库,以及项目的生成器。

最新版本 conan(2.10.2) 不再支持 cmake 生成器,仅支持 CMakeDeps、CMakeToolchain

1
2
3
4
5
6
7
8
9
10
[requires]
jsoncpp/1.9.5

[generators]
CMakeDeps
CMakeToolchain

[options]
# conan管理的第三方库默认是以静态库lib的形式集成到项目中去的,如果需要动态库dll形式,则需要添加以下内容
# jsoncpp/1.9.5:shared=True

jsoncpp 是一个帮助 c++处理 json 数据的库,在 conanfile.txt 中添加如下内容,表示依赖 jsoncpp/1.9.5 版本的 jsoncpp。

CMakeLists.txt

CMakeLists.txt 是 cmake 在本项目下的配置文件,描述了项目的编译选项,以及链接依赖库,参考在 Windows 下使用 CMake 构建和管理第三方库

1
2
3
4
5
6
7
8
9
10
11
12
13
cmake_minimum_required(VERSION 3.15)

# 如果是C项目,需要将下面的 CXX 改为 C
project(compressor CXX)

# 引入conan生成的cmake文件
# 在conan install时,会生成conandeps_legacy.cmake文件,这里需要引入进来,后面才能使用CONANDEPS_LEGACY
include(build/conandeps_legacy.cmake)

add_executable(${PROJECT_NAME} src/main.cpp)

# 链接依赖库,CONANDEPS_LEGACY是conan生成的cmake文件里的变量,包含引用的依赖库列表
target_link_libraries(${PROJECT_NAME} ${CONANDEPS_LEGACY})

src/main.cpp

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
#include <string.h>
#include <iostream>

#include <json/json.h>

int main(void)
{
// JSON 字符串
const char *jsonString = R"({
"name": "John Doe",
"age": 30,
"is_student": false,
"grades": [90, 85, 88]
})";

// 解析 JSON 字符串
Json::CharReaderBuilder readerBuilder;
Json::Value root;
std::string errs;
std::istringstream s(jsonString);
bool parsingSuccessful = Json::parseFromStream(readerBuilder, s, &root, &errs);

if (!parsingSuccessful)
{
std::cerr << "Failed to parse JSON: " << errs << std::endl;
return 1;
}

// 访问 JSON 数据
std::string name = root["name"].asString();
int age = root["age"].asInt();
bool isStudent = root["is_student"].asBool();
Json::Value grades = root["grades"];

std::cout << "Name: " << name << std::endl;
std::cout << "Age: " << age << std::endl;
std::cout << "Is Student: " << (isStudent ? "Yes" : "No") << std::endl;
std::cout << "Grades: ";
for (const auto &grade : grades)
{
std::cout << grade.asInt() << " ";
}
std::cout << std::endl;

return 0;
}

编译

编译时可能会需要 python、ninja、nasm 等工具,如遇报错,请优先查看工具是否安装,并且是否兼容。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 第一次编译时,需要执行下列命令,获取平台信息
conan profile detect


# 在项目根目录执行conan install
# --output-folder=build 表示将conan生成的文件保存在build目录下
# --build=missing 表示如果没有预编译的库,就下载源码来编译
# --profile=myProfile 表示使用自定义的myProfile配置文件
conan install . --output-folder=build --build=missing --profile=myProfile


# 进入build目录
cd build


# 生成 Makefile
cmake .. -G "MinGW Makefiles" -DCMAKE_TOOLCHAIN_FILE="conan_toolchain.cmake" -DCMAKE_BUILD_TYPE=Release


# 编译
cmake --build . --config Release

profile

使用 conan profile detect 命令自动生成的 profile 文件会根据环境的不同生成不同的内容。

参考 windows 环境下会生成的内容:

1
2
3
4
5
6
7
8
[settings]
arch=x86_64
build_type=Release
compiler=gcc
compiler.cppstd=gnu17
compiler.libcxx=libstdc++11
compiler.version=14
os=Windows

参考 linux 环境下会生成的内容:

1
2
3
4
5
6
7
8
[settings]
arch=x86_64
build_type=Release
compiler=gcc
compiler.cppstd=gnu17
compiler.libcxx=libstdc++11
compiler.version=11
os=Linux

自定义 profile

如果你想交叉编译,则可以通过自定义 profile 来实现。

例如在 Linux 系统上构建 windows 项目,则可以通过自定义 profile 来实现。参考内容如下:

1
2
3
4
5
6
7
8
[settings]
arch=x86_64
build_type=Release
compiler=gcc
compiler.cppstd=gnu17
compiler.libcxx=libstdc++11
compiler.version=14
os=Windows

可以注意到,os 被替换为了 Windows,代表编译目标的运行环境。

添加编译器路径到系统环境变量

在执行 conan profile detect 之前,一定要确保编译器已经在系统环境变量中配置好。最好是在系统中永久配置好,当然如果你想临时设置,也可以通过命令行设置。

特别注意:CC 和 CXX 的值,一定要以斜杠(/)分隔,不用使用反斜杠(\),否则构建会失败,这是因为构建期间会涉及到 Windows 文件系统之外的文件系统,比如 linux 系统就不支持使用反斜杠作为路径分隔符。

1
2
3
# 临时设置(cmd)
set CC=path/to/your/gcc.exe
set CXX=path/to/your/g++.exe
1
2
3
# 临时设置(powershell)
$env:CC="path/to/your/gcc.exe"
$env:CXX="path/to/your/g++.exe"

如果是在Linux系统上进行交叉编译

1
2
export CC=x86_64-w64-mingw32-gcc
export CXX=x86_64-w64-mingw32-g++

其他

本地库目录

一般 conan 安装的包都会保存在 C:\Users\yourUserName.conan2\p\b 目录下,安装时会自动添加到系统环境变量中。代码中可以使用尖括号 <> 来引用本地库,例如:

1
#include <json/json.h>

vscode 语法高亮

需要在项目中添加 .vscode\c_cpp_properties.json 文件,

添加 “C:/Users/yourUserName/.conan2/p/b/**“,

完整内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
"configurations": [
{
"name": "Win32",
"includePath": [
"${workspaceFolder}/**",
"C:/Users/yourUserName/.conan2/p/b/**"
],
"defines": ["_DEBUG", "UNICODE", "_UNICODE"],
"compilerPath": "D:\\MinGW\\mingw64\\bin\\gcc.exe",
"cStandard": "c17",
"cppStandard": "gnu++14",
"intelliSenseMode": "windows-gcc-x64"
}
],
"version": 4
}

参考

Build a simple CMake project using Conan - conan 2.10.2
C/C++ 包管理器 Conan 使用指南 - conan 1.48.0
在 Windows 下使用 CMake 构建和管理第三方库

  • 标题: c++包管理器conan的使用
  • 作者: 木头的喵喵拖孩
  • 创建于: 2024-12-11 14:58:40
  • 更新于: 2024-12-30 17:56:18
  • 链接: https://blog.xx-xx.top/2024/12/11/c-包管理器conan的使用/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。