系列文章目录
前言
C++包管理工具conan简介。
conan实际上是用python编写的一个python module,用于C/C++的包管理,基于C/S模式,client向server端请求二进制包。
构建工具栈:
+-------------------------+
| conan |
+-------------------------+
| cmake(or others) |
+-------------------------+
| make(or others) |
+-------------------------+
| gcc(or others) |
+-------------------------+
0、安装
# 安装python虚拟环境管理模块
pip install venv
# 创建虚拟环境
# 这里会在当前目录下创建一个.venv目录,
python3 -m venv ./.venv
# 激活虚拟环境。 激活虚拟环境后所有通过pip安装的模块都会在该目录下,不会与全局环境冲突
source .venv/bin/activate
# 在虚拟环境中安装conan
pip install conan
分享依赖给他人
# 导出当前依赖
pip freeze > requirements.txt
# 安装所有需要的模块
pip install -r requirements.txt
一、使用conan管理项目依赖
使用conan构建一个简单的CMake项目
├── CMakeLists.txt
├── conanfile.txt
└── src
└── main.c
CMakeLists.txt
find_package(ZLIB REQUIRED)
conanfile.txt
[requires] 段用于声明项目中需要用到的库
[generators] 段告诉 Conan 生成一个文件,该文件将用于编译器或构建系统查找依赖项和构建项目。在本例中,由于我们的项目基于 CMake,我们将使用 CMakeDeps 来生成有关 Zlib 库文件安装位置的信息,并使用 CMakeToolchain 通过 CMake 工具链文件将构建信息传递给 CMake。
[requires]
zlib/1.3.1
[generators]
CMakeDeps
CMakeToolchain
Conan profile 允许用户定义配置,如,指定编译器、构建选项、架构、共享或静态库等。Conan默认不自动检测profile
# 该指令
conan profile detect --force
这将根据环境检测操作系统、构建架构和编译器设置。它还会默认将构建配置设置为“Release”。生成的配置文件将以“default”的名称存储在Conan的主文件夹中,除非通过命令行指定了其他配置文件,否则Conan在所有命令中都会默认使用该配置文件。
conan install . --output-folder=build --build=missing
- Conan从远程服务器安装了Zlib库,如果该库可用,默认情况下该服务器应为Conan Center服务器。此服务器既存储Conan配方(定义如何构建库的文件),也存储可重用的二进制文件,这样我们就不必每次都从源代码构建。
- Conan在build文件夹下生成了几个文件。这些文件是由我们在conanfile.txt中设置的CMakeToolchain和CMakeDeps生成器生成的。CMakeDeps生成文件,以便CMake能够找到我们刚刚下载的Zlib库。另一方面,CMakeToolchain为CMake生成一个工具链文件,这样我们就可以使用为默认配置文件检测到的相同设置,通过CMake透明地构建我们的项目。
- –build=missing:当预编译包缺失时自动从源码构建
- –install-folder:指定生成文件的输出目录
- –settings、–options:指定构建配置(如编译器版本、架构等)
conan install的核心作用:准备cmake环境
- 依赖解析与获取
- 读取项目根目录下的 conanfile.txt或 conanfile.py
- 解析依赖图(包括传递依赖)
- 从配置的远程仓库(如 conancenter)下载预编译的二进制包
- 如果预编译包不可用,则根据 settings和 options在本地从源码构建
- 环境配置与集成文件生成
- 为每个依赖包生成对应的 .cmake或 .pc文件
- 创建 conanbuildinfo.cmake(旧版本)或 conan_toolchain.cmake(新版本)
- 设置编译器和链接器所需的路径、定义、库文件、脚本等信息
$ cd build
$ cmake .. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Release
$ cmake --build .
Conan 命令行
$ conan config home
$ conan install . --build=missing --profile=default
$ conan install . --output-folder=build --build=missing --settings=build_type=Debug
$ conan install . --output-folder=build --build=missing --options=zlib/1.3.1:shared=True
conan编译会自动生成程序的运行环境:
source conanrun.sh
source deactivate_conanrun.sh
conanfile.py文件
conanfile.txt
[requires]
zlib/1.3.1
[tool_requires]
cmake/3.27.9
[generators]
CMakeDeps
CMakeToolchain
conanfile.py
from conan import ConanFile
class CompressorRecipe(ConanFile):
settings = "os", "compiler", "build_type", "arch"
generators = "CMakeToolchain", "CMakeDeps"
def requirements(self):
self.requires("zlib/1.3.1")
def build_requirements(self):
self.tool_requires("cmake/3.27.9")
- settings: 类属性,定义项目维度的变量,如编译器、它的版本、OS
- generators: 类属性,说明调用conan install命令时,哪个Conan生成器会运行
- requirements() 方法,使用
self.requires()方法声明 zlib/1.3.1 依赖 - build_requirements() 方法,使用
self.tool_requires()方法声明 cmake/3.27.9 依赖
$ conan install . --output-folder build --build=missing
$ cd build
$ source conanbuild.sh
Capturing current environment in deactivate_conanbuildenv-release-x86_64.sh
Configuring environment variables
$ cmake .. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Release
$ cmake --build .
layout() 方法
如:通过layout()方法,可以直接根据CMake generator的类型指定输出目录名
def layout(self):
# We make the assumption that if the compiler is msvc the
# CMake generator is multi-config
multi = True if self.settings.get_safe("compiler") == "msvc" else False
if multi:
self.folders.generators = os.path.join("build", "generators")
self.folders.build = "build"
else:
self.folders.generators = os.path.join("build", str(self.settings.build_type), "generators")
self.folders.build = os.path.join("build", str(self.settings.build_type))
self.folders.generators=指定生成目录
self.folders.build=Makefile所在目录
这里有一些预定义的layouts以供import和直接使用,如,cmake_layout()
from conan.tools.cmake import cmake_layout
def layout(self):
cmake_layout(self)
使用 validate() 方法对不支持的配置抛出错误
from conan.errors import ConanInvalidConfiguration
class CompressorRecipe(ConanFile):
...
def validate(self):
if self.settings.os == "Macos" and self.settings.arch == "armv8":
raise ConanInvalidConfiguration("ARM v8 not supported in Macos")
条件requirements
向requirements()方法中添加或移除requirements
from conan import ConanFile
class CompressorRecipe(ConanFile):
# binary configuration
settings = "os", "compiler", "build_type", "arch"
generators = "CMakeToolchain", "CMakeDeps"
def requirements(self):
self.requires("zlib/1.3.1")
if self.settings.os == "Windows":
self.requires("base64/0.4.0")
def build_requirements(self):
if self.settings.os != "Windows":
self.tool_requires("cmake/3.27.9")
使用 generate() 方法从packages中拷贝资源
import os
from conan import ConanFile
from conan.tools.files import copy
class Recipe(ConanFile):
...
def generate(self):
# Copy all resources from the dependency's resource directory
# to the "assets" folder in the source directory of your project
dep = self.dependencies["dep_name"]
copy(self, "*", dep.cpp_info.resdirs[0], os.path.join(self.source_folder, "assets"))
conan install 就会拷贝资源文件
** 使用build() 方法和conan build命令 **
如果Conan配方里实现了build()方法,那么一条conan build命令就可以实现conan install + cmake <configure> + cmake <build>
from conan import ConanFile
from conan.tools.cmake import CMake
class CompressorRecipe(ConanFile):
settings = "os", "compiler", "build_type", "arch"
generators = "CMakeToolchain", "CMakeDeps"
...
def build(self):
cmake = CMake(self)
cmake.configure()
cmake.build()
交叉编译
build profile: 编译主机
host profile: 运行编译产物的主机
conan install . --build=missing --profile=someprofile
# 等价于
conan install . --build=missing --profile:host=someprofile --profile:build=default
conan install . --build missing -pr:b=default -pr:h=./profiles/raspberry
<local folder>/profiles/raspberry
[settings]
os=Linux
arch=armv7hf
compiler=gcc
build_type=Release
compiler.cppstd=gnu17
compiler.libcxx=libstdc++11
compiler.version=12
[buildenv]
CC=arm-linux-gnueabihf-gcc-12
CXX=arm-linux-gnueabihf-g++-12
LD=arm-linux-gnueabihf-ld
[buildenv] 用于设置环境变量。将该段添加到profile文件后,执行 conan install 将会调用VirtualBuildEnv生成器,该生成器将会把环境信息添加到 conanbuild.sh 脚本中,该脚本会在CMake之前source一下以使用交叉构建工具链。
host context 是编译产物时用到的,通过self.requires()添加
build context 包含[tool requirements],在build machine中使用
两个context互不影响
versioning
def requirements(self):
self.requires("zlib/[~1.2]") # 1.2.X的最新版
"zlib/[<1.2.12]" # zlib版本小于1.2.12的最新版
def build_requirements(self):
self.tool_requires("cmake/[>3.10]") # 至少是cmake3.11的版本
pkgname/version#recipe_reversion
or
pkgname/version#user/channel#recipe_revision
# 查看修订的版本
conan list "zlib/1.2.12#*" -r=conancenter
self.requires("zlib/1.2.12#87a7211557b6690ef5bf7fc599dd8349")
Lockfiles 是指包含固定依赖的列表,该列表指明了依赖的固定版本
lockfile可以被认为是某个时间点的依赖图的快照
conan lock create .
# then
conan install . 等价于 conan install . --lockfile=conan.lock
此时会强制使用conan.lock中的配置
752

被折叠的 条评论
为什么被折叠?



