当前位置: 首页 > 工具软件 > Conan > 使用案例 >

Conan——C++包管理工具

凌运恒
2023-12-01

Conan——C++包管理工具——使用踩坑记录
使用conan所遇到的大部分问题都可以在conan官方文档中找到答案,

参考官方文档地址:

https://docs.conan.io/en/latest/

虽然大多数情况下,答案不是那么显然。

不过也正是如此,本文把那些可能有点绕的问题的解决办法和原理,尽可能详细的记录下来,

以便后人遇到相同问题时能节省一点定位的时间。

创建一个包的最简步骤
1. conan new 生成一个conanfile.py
2. 编辑conanfile.py
一般的,代码的版本控制不在conan中进行,也不推荐这么做,你有更好的选择:git

from conans import ConanFile, CMake, tools
 
 
class BgyArTopicConan(ConanFile):
    name = "bgy_ar_topic"
    version = "v1.0.0"
    ........some informations........
    settings = "os", "compiler", "build_type", "arch"
    requires = ["myjson/v1.0.0@ar/stable"]
 
    def source(self):
        self.run("git clone git@10.8.202.206:agricultural_robot/ros/common/bgy_ar_topic.git")
        # This small hack might be useful to guarantee proper /MT /MD linkage
        # in MSVC if the packaged project doesn't have variables to set it
        # properly
        tools.replace_in_file("bgy_ar_topic/CMakeLists.txt", "project(bgy_ar_topic)",
                              '''project(bgy_ar_topic)
include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
conan_basic_setup()''')
 
    def build(self):
        cmake = CMake(self)
        cmake.configure(source_folder="bgy_ar_topic")
        cmake.build()
 
    def package(self):
        self.copy("*.h", dst="include", src="bgy_ar_topic/include")
        self.copy("*.so", dst="lib", src="lib", keep_path=False)
        self.copy("*.a", dst="lib", src="lib", keep_path=False)
 
    def package_info(self):
        self.cpp_info.libs = tools.collect_libs(self)
 
很显然,在conanfile.py文件中定义了几个方法,并且依赖了一个包:myjson

其中source方法是用来获取代码用的,比如在上面示例中,source方法正是将代码拉取到了本地仓库的source目录下

 ~/.conan/data/bgy_ar_topic/v1.0.0/ar/stable/source$ ls
bgy_ar_topic
在拉取到代码之后,将bgy_ar_topic中的CMakeLists.txt文件中的内容

project(bgy_ar_topic)
# other configures
....
替换成如下内容

project(bgy_ar_topic)
include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
conan_basic_setup()
# other configures
....
这conanbuildinfo.cmake正是conan生成的让bgy_ar_topic找到myjson包的头文件和lib的文件。

conan_basic_setup() 是conanbuildinfo.cmake到处的cmake方法。

通过调用这个方法,可以使bgy_ar_topic工程在编译时能够找到其依赖的包的头文件和库。

3. conan create 
通过下面指令创建包bgy_ar_topic/v1.0.0@ar/stable

$conan create --profile=ros . ar/stable
创建后,在conan本地仓库中会多出这个目录:

 ~/.conan/data/bgy_ar_topic/v1.0.0/ar/stable
 构造过程
创建时执行的构建将在 ~/.conan/data/bgy_ar_topic/v1.0.0/ar/stable/build/中进行,回顾一下前面的conanfile.py

 def build(self):
        cmake = CMake(self)
        cmake.configure(source_folder="bgy_ar_topic")
        cmake.build()
在定义build方法时,这里暗示执行cmake指令的工作目录为

 ~/.conan/data/bgy_ar_topic/v1.0.0/ar/stable/build/c023db9fc677d4d0b3bd0c20f71385e4cf8a1220
注意到这一串很长的代码了吧,这就是构造标识码,这个码也会在 ~/.conan/data/bgy_ar_topic/v1.0.0/ar/stable/package中出现。

这个build方法相当于执行以下shell指令

~/.conan/data/bgy_ar_topic/v1.0.0/ar/stable/build/c023db9fc677d4d0b3bd0c20f71385e4cf8a1220$ cmake bgy_ar_topic
...
something outputs
...
~/.conan/data/bgy_ar_topic/v1.0.0/ar/stable/build/c023db9fc677d4d0b3bd0c20f71385e4cf8a1220$ make 
...
something outputs
...
打包过程
打包bgy_ar_topic包的时候,将在 ~/.conan/data/bgy_ar_topic/v1.0.0/ar/stable/build/中进行,回顾一下前面的conanfile.py

 def package(self):
        self.copy("*.h", dst="include", src="bgy_ar_topic/include")
        self.copy("*.so", dst="lib", src="lib", keep_path=False)
        self.copy("*.a", dst="lib", src="lib", keep_path=False)
注意这里使用的self.copy方法,其中dst暗示的工作目录为~/.conan/data/bgy_ar_topic/v1.0.0/ar/stable/package/

而src所暗示的工作目录则是~/.conan/data/bgy_ar_topic/v1.0.0/ar/stable/build/

所以说,package中做的就是将你想要打包的文件从~/.conan/data/bgy_ar_topic/v1.0.0/ar/stable/build/中,拷贝到~/.conan/data/bgy_ar_topic/v1.0.0/ar/stable/package/中

在本例中,会将~/.conan/data/bgy_ar_topic/v1.0.0/ar/stable/build/bgy_ar_topic/include中的所有头文件复制到~/.conan/data/bgy_ar_topic/v1.0.0/ar/stable/package/include中

将~/.conan/data/bgy_ar_topic/v1.0.0/ar/stable/build/lib中的所有动态库和静态库拷贝到~/.conan/data/bgy_ar_topic/v1.0.0/ar/stable/package/lib中

发布自己的包
发布包需要使用conan upload指令

conan upload bgy_ar_topic/v1.0.0@ar/stable
使用这一条指令的时候,会将本地conan仓库中的bgy_ar_topic/v1.0.0@ar/stable上传到远程库

远程仓库在哪里,怎么添加私有的远程仓库?怎么看到当前支持的远程仓库?

$ conan remote add ar-conan-host http://10.8.203.98:8081/repository/ar-conan-host/
$ conan remote list
ar-conan-host: http://10.8.203.98:8081/repository/ar-conan-host/ [Verify SSL: True]
conan upload bgy_ar_topic/v1.0.0@ar/stable -r ar-conan-host
这样,就指定远程仓库是ar-conan-host仓了,并将b'g'y_ar_conan包的打包信息上传,注意,此时并没有把生成物package目录中的内容上传。

需要注意的是,conan在上传之前是需要登录一下仓库的,因为远程仓库做了安全设置,不是谁都能有权限上传私有包的。所以你需要登录一下:

conan user -p 666666 -r ar-conan-host master
conan 使用用户:master,密码666666, 登录到ar-conan-host仓库,

很多时候,我们的用户并不希望构造我们生成的包,所以上传包的时候,把我们打包好的生成物上传是一个好的选择:

$ conan upload bgy_ar_topic/v1.0.0@ar/stable -r ar-conan-host --all
在上传的时候添加一个参数--all即可,现在你的仓库中不止有包的配方,还有一套生成好的包。

了解Conan的本地仓库
所谓的本地仓库,并没有那么神秘,它静静的躺在我们用户目录下,

对于Linux

/home/user/.conan/data/
对于windows

C:/Users/user/.conan/data/
当执行

$conan new task_control/v1.0.0
$conan create --profile=default . test/test
之后,会在本地目录自动生成这个目录

~/.conan/data/task_control/v1.0.0/test/test$ ls
build   export_source  metadata.json       package
export  locks          metadata.json.lock  source
具体的操作对本地仓库会有什么影响,我相信,认真看过”创建一个包的最简步骤“这一节内容之后,你已经有了认识。所以这里我不想过多赘述。

 类似资料: