官方教程:
https://docs.conan.io/2/tutorial.html
https://docs.conan.io/2/tutorial/developing_packages/local_package_development_flow.html
安装
官方教程:https://docs.conan.io/2/installation.html
pip3 install --upgrade conan |
配置默认设置
conan profile detect |
我的偏好:
compiler.cppstd=17 |
创建包
在工程的根目录下执行:
conan new cmake_exe -d name=包名 -d version=0.1.0 |
如果是库的话:
conan new cmake_lib -d name=包名 -d version=0.1.0 |
然后编辑CMakeLists.txt
和conanfile.py
。
conanfile.py
requirements
定义包的依赖。例子:
def requirements(self): |
官方文档:https://docs.conan.io/2/tutorial/versioning/version_ranges.html#range-expressions
generate
在conan install
的时候被调用,用于生成用于编译的文件。
build
在conan build
的时候被调用,用于编译。
package
在打包的时候被调用。
package_info
提供包的各种信息,供其他包使用。
cpp_info.libs
:
此包提供的其他包应该链接的库,通常放在libs
文件夹里。
cpp_info.system_libs
:
此包依赖的系统库。依赖此包的其他包会继承此依赖。
参考:question: difference between “cpp_info.libs” and “cpp_info.system_libs”
cpp_info.set_property("cmake_target_name", "xxxx")
:
给出这个库的cmake
target的名字。这样依赖这个库的其他包在它自己的CMakeLists.txt
里用find_package
找这个包之后就能用这个包里给出的target了。
参考:https://docs.conan.io/2/tutorial/creating_packages/define_package_information.html
例子
生成可执行文件的包
CMakeLists.txt
:
cmake_minimum_required(VERSION 3.15) |
conanfile.py
:
from conan import ConanFile |
只有头文件的包 (header-only)
文档:https://docs.conan.io/2/tutorial/creating_packages/other_types_of_packages/header_only_packages.html
完整工程:https://github.com/seekstar/counter-timer-cpp
CMakeLists.txt
:
cmake_minimum_required(VERSION 3.15) |
conanfile.py
:
from conan import ConanFile |
含多个库的包 (package with multiple libraries)
只有头文件的含多个库的包 (header-only package with multiple libraries)
例子:https://github.com/seekstar/rcu-vector
坑点:如果库a
是header-only的话,不能把自己(也就是a
)放进self.cpp_info.components['a'].libs
,因为libs
表示依赖这个库的其他库需要链接的库,而header-only的库不能被链接。
生成用于编译的辅助文件
conan install . |
默认生成在build
目录下面。
编译
conan build . |
如果之前没有执行conan install .
的话会自动执行conan install .
。
打包并添加到local cache
conan create . |
如果之前没有执行conan build .
的话会自动执行之。
Debug版本:
conan create . -s build_type=Debug |
从local cache删除:
conan remove 包名/x.x.x@ |
详见官方文档:https://docs.conan.io/1/reference/commands/misc/remove.html
conan.lock
固定所有依赖版本,避免未来有依赖更新之后无法编译。注意,只有当前包是end product的时候才能锁依赖版本。如果当前包是一个库,就不应该锁依赖版本,因为使用这个库的包可能想用别的版本。
创建conan.lock
:
conan lock create . |
创建完了之后好像会自动被用上。
从conan.lock
中清楚unused locked versions:
conan lock create . --lockfile-clean |
官方文档:https://docs.conan.io/2/tutorial/versioning/lockfiles.html
Conan server
可以自己部署一个conan server并将打好的包上传上去,方便团队协作。
安装
pip3 install conan-server |
配置
官方文档:https://docs.conan.io/2/reference/conan_server.html
编辑~/.conan_server/server.conf
。一些比较重要的项如下。
[users]
格式是用户名: 密码
。密码是明文保存的,差评。
安全起见,建议把demo: demo
删掉,换上自己的。
[write_permissions]
默认为空。虽然上面的注释说author可以write自己的包,但是好像没法上传新的包。所以我直接设置成了所有已登录用户都可以写:
*/*@*/*: ? |
运行
conan_server |
添加到remote list
conan remote add remote名字 http://localhost:9300 |
删除:conan remote remove remote名字
登录
conan remote login remote名字 用户名 |
或者直接提供密码:
conan remote login remote名字 用户名 -p 密码 |
上传
官方文档:https://docs.conan.io/2/tutorial/conan_repositories/uploading_packages.html
conan upload 包名 -r=remote名 |
注意这里只上传已经构建的版本。所以最好先构建release和debug,再把它们一起上传:
conan create . && conan create . -s build_type=Debug |
搜索包
这里列出所有包:
conan search "*" -r=remote名 |
将变量传给cmake
网上通常说是通过cmake.definitions
:passing command
line arguments to cmake during conan build
但是在conan2上会报这个错:AttributeError: 'CMake' object has no attribute 'definitions'
实际上应该用cmake.configure的cli_args参数把变量传给cmake:
options = { |
参考:https://docs.conan.io/2/reference/tools/cmake/cmake.html#conan.tools.cmake.cmake.CMake.configure
已知的问题
测试
conan test test_package 包名/版本 -s build_type=Debug --build missing |
其中包名/版本
不可忽略。感觉应该默认为当前包的最新版本。
此外,没找到怎么直接在conan test
的时候把参数传进去。好像只能通过直接运行./test_package/build/gcc-10-x86_64-17-release/test 参数1 参数2
来传参。
与conan2不兼容的包
(2023.07.07) userspace-rcu
会自动使用用nix-env
安装的库
比如用nix-env
安装了gflags之后,conan会自动使用它,但是与此同时会使用系统安装的glibc。但是nix-env
安装的gflags通常依赖高版本的glibc,如果系统里自带的glibc版本过低,就会报链接错误。这时只需要nix-env -e gflags
,让conan使用系统自带的gflags即可。