# conan使用指南
# 使用conan 包
下载示例工程
$ git clone https://github.com/conan-io/examples2.git
$ cd examples2/tutorial/consuming_packages/simple_cmake_project
上述工程会依赖zlib, 在使用conan管理包的时候,会从ConanCente中拉取需要的包,上述工程中包含conanfile.txt就是为了说明需要获取的conan包的版本信息。
[requires]
zlib/1.2.11
[generators]
CMakeDeps
CMakeToolchain
上面文件中,[generators]这一部分定义了 Conan 应该使用的生成器。生成器是 Conan 的一个组件,它负责生成构建系统所需的文件。CMakeDeps:这是一个生成器,它会生成一个 conan_cmake_find_package.cmake 文件,这个文件可以用来在 CMake 项目中查找 Conan 管理的包。CMakeToolchain:这是另一个生成器,它会生成一个 conan_toolchain.cmake 文件,这个文件包含了构建项目所需的工具链配置,比如编译器设置、CMake 版本等。
conan profile detect --force
上面的命令用来创建或更新一个 Conan 用户配置文件(profile),这个文件包含了构建环境的设置,如编译器、架构、操作系统等信息。
detect_api: Found cc=gcc- 13.2.0
detect_api: gcc>=5, using the major as version
detect_api: gcc C++ standard library: libstdc++11
Detected profile:
[settings]
arch=x86_64
build_type=Release
compiler=gcc
compiler.cppstd=gnu17
compiler.libcxx=libstdc++11
compiler.version=13
os=Linux
WARN: This profile is a guess of your environment, please check it.
WARN: The output of this command is not guaranteed to be stable and can change in future Conan versions.
WARN: Use your own profile files for stability.
Saving detected profile to /home/lx/.conan2/profiles/default
可以使用如下命令获取conan的配置文件默认的路径,
conan config home
# /home/lx/.conan2
profile文件中包含不同的部分,[settings]包含了操作系统、体系结构、编译器和构建的配置,当使用conan指令带--profile参数时,相关的配置将都会从profile文件中读取,当不指定这个参数的时候,默认的会从--profile=default中读取。可以使用不同的profile文件来配置不同的构建设置。在conan命令中使用--settings参数可以覆盖掉profile中的setting设置。可以使用如下代码来确认setting参数有没有生效,
#include <cstdio>
int main() {
#ifdef NDEBUG
printf("Not debug\n");
#else
prinf("debug\n");
#endif
return 0;
}
编译的时候使用的参数如下:
conan install . --output-folder=build --build=missing --settings=build_type=Debug
接下来将使用 Conan 安装 Zlib 并生成 CMake 所需的文件来查找该库并构建我们的项目。我们将在文件夹 build 中生成这些文件。为此,请运行:
conan install . --output-folder=build --build=missing
构建仓库:
cmake .. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Release
cmake中的CMAKE_TOOLCHAIN_FILE变量非常有用,它允许用户指定一个工具链文件,这个文件定义了构建系统的环境和编译器设置。工具链文件通常用于跨平台构建,或者当你需要自定义编译器、编译选项、链接器等设置时。
# 将构建工具也作为conan包进行管理
上面的示例中使用的是系统中已经安装的cmake,有时候需要使用conan包来指定要使用的cmake版本,本节就来介绍如何使用conan来安装指定版本的cmake来进行编译系统的构建。
以上操作其实非常简单,只需要在conanfile.txt中进行指定即可,如下:
[requires]
zlib/1.2.11
[tool_requires]
cmake/3.22.6
[generators]
CMakeDeps
CMakeToolchain
在指定cmake‵版本之前,还是需要系统先有一个cmake,因为conanfile中指定的cmake`版本只是指定在当前的工程中。
在cmake文件中添加一行打印使用cmake的版本信息:
message("Building with CMake version: ${CMAKE_VERSION}")
执行上述命令后,在build文件夹下将有如下文件conanbuild.sh,这个脚本自动调用VirtualBuildEnv生成器,这个脚本会设置一些环境变量如$PATH来指定我们的软件路径,如新安装的cmake。
source conanbuild.sh # 激活当前环境
cmake --version
# cmake version 3.22.6
同样在build文件夹中还有deactivate_conanbuild.sh文件用来恢复系统环境变量的设置,
source deactivate_conanbuild.sh # 恢复环境变量设置
# 应用依赖设置
默认情况下,conan生成目标文件使用的是静态链接的方式,通过设置conan的--options参数可以设置目标文件是静态链接还是动态链接的方式,
conan install . --output-folder=build --build=missing --options=zlib/1.2.11:shared=True
使用上述命令的时候会在build目录下生成‵conanrun.sh脚本设置VirtualRunEnv环境相关的变量,如LD_LIBRARY_PATH和PATH`,供执行可执行文件的时候使用,如执行共享库的路径。
conan中settings和options的区别:
settings是项目范围的配置,会影响正在构建的整个项目。例如,操作系统(os)、架构(arch)和编译器(compiler)等设置,对于依赖关系图中的所有包来说,这些设置通常是相同的。options是特定于包的配置。例如,静态或共享库不是适用于所有包的设置。有些包可能只包含头文件,而其他包可能包含数据或可执行文件。shared是一个常见的选项,但包可以定义和使用任何它们需要的选项。
# 使用conanfile.py
简单场景使用conanfile.txt就足够了,但想更灵活的使用conan就需要使用conanfile.py了,可以在其中使用 Python 代码来执行诸如动态添加需求、根据其他选项更改选项或根据需求设置选项等操作。
将以下conanfile.txt改造成conanfile.py文件:
# conanfile.txt
[requires]
zlib/1.2.11
[tool_requires]
cmake/3.22.6
[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.2.11")
def build_requirements(self):
self.tool_requires("cmake/3.22.6")
这个类CompressorRecipe继承自ConanFile类,这个类有不同的settings/gennerators配置,
requirements()方法中调用self.requires方法来指定zlib依赖build_requirements()方法中使用self.tool_requires()来指定编译工具等的使用
其他的conan build/install指令的使用方式和使用conanfile.txt时一样不要变更。
在前面的示例中,每次执行 conan install 命令时,我们都必须使用 –output-folder 参数来定义要创建 Conan 生成的文件的位置。有一种更简洁的方法来决定我们希望 Conan 在哪里为构建系统生成文件,例如如果我们想要根据我们使用的 CMake 生成器的类型来设置不同的输出文件夹, 可以直接在conanfile.py layout()方法中定义它,并使其适用于每个平台,而无需添加更多更改。
# 使用layout方法
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,layout()方法中可以通过设置这个属性来指定Conan生成的所有辅助文件(CMake 工具链和 cmake 依赖文件)放置的文件夹
# 使用validate方法
当conan加载conanfile.py文件时,还会自动执行validate函数,可以进行一些配置的校验。
def validate(self):
if self.settings.os == "Macos" and self.settings.arch == "armv8":
raise ConanInvalidConfiguration("ARM v8 not supported in Macos")
# 使用generate()方法从pkg中复制资源
在某些场景中,conan pkg中包含有对使用pkg的人来说十分重要的文件,像配置文件/assert等,使用generate()方法可以将这些文件从conan cache中拷贝到工程文件夹中,确保所有的资源可以被正确的使用。
如下的示例代码功能是将pkg resdirs目录下的资源文件拷贝到工程asserts文件夹下,
import os
from conan import ConanFile
from conan.tools.files import copy
class MyProject(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命令后,所有的资源文件将会被拷贝到本地,如此就可以在本地工程中使用配置文件来构建了。
# 交叉编译
譬如在x86 64的ubuntu上编译,在Raspberry Pi上运行。conan使用两个编译配置文件高的profile,即便对于本地编译运行的conan构建,也可以看做其使用了两套profile,如下:
conan install . --build=missing --profile:host=someprofile --profile:build=default
profile:host:这是定义构建的二进制文件将运行的平台的配置文件。对于我们的字符串压缩器应用程序,此配置文件将应用于将在Raspberry Pi中运行的Zlib库。profile:build:这是定义将构建二进制文件的平台的配置文件。对于我们的字符串压缩器应用程序,CMake 工具将使用此配置文件,该工具将在Ubuntu Linux计算机上对其进行编译。
仅设置--profile参数时,等价于设置profile:host,--profile:build将使用默认配置。
# build.profile
[settings]
os=Linux
arch=x86_64
build_type=Release
compiler=gcc
compiler.cppstd=gnu14
compiler.libcxx=libstdc++11
compiler.version=9
# host.profile
[settings]
os=Linux
arch=armv7hf
compiler=gcc
build_type=Release
compiler.cppstd=gnu14
compiler.libcxx=libstdc++11
compiler.version=9
[buildenv]
CC=arm-linux-gnueabihf-gcc-9
CXX=arm-linux-gnueabihf-g++-9
LD=arm-linux-gnueabihf-ld
对应的conanfile.py文件内容基本上不变:
from conan import ConanFile
from conan.tools.cmake import cmake_layout
class CompressorRecipe(ConanFile):
settings = "os", "compiler", "build_type", "arch"
generators = "CMakeToolchain", "CMakeDeps"
def requirements(self):
self.requires("zlib/1.2.11")
def build_requirements(self):
self.tool_requires("cmake/3.22.6")
def layout(self):
cmake_layout(self)
编译使用的命令为:
conan install . --build missing -pr:b=default -pr:h=./profiles/raspberry
使用file命令可以查看编译生成的可执行文件的目标架构是aarch64。
# conan常用配置
- 添加新的REMOTE仓库地址
# 添加
conan remote add my_private_repo https://myrepo.example.com/api/conan/repo
# 移除
conan remote remove my_private_repo
# 列出
conan remote list
# conancenter: https://center2.conan.io [Verify SSL: True, Enabled: True]
conan remote的配置在remotes.json文件中
{
"remotes": [
{
"name": "conancenter",
"url": "https://center2.conan.io",
"verify_ssl": true
}
]
}
- 管理缓存
# 移除某个包的缓存,例如包corrupted的时候,使用会报错
conan remove ffmpeg/7.1.3 -c
- 查看conan相关配置
# 查看配置文件路径
conan config home
# global.conf