You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Conan 2.x分发C++共享库并实现多版本部署?

问题背景与需求

我维护一个包含4个基础库和N个依赖这些库的可执行文件的单仓库(monorepo),目前用Conan 2.x的孵化版workspaces特性管理构建。所有库和应用都已通过Conan打包推送到Artifactory,且希望将这4个库作为共享库交付。

核心需求:

  • 能在同一裸机上并存同一共享库的多个版本,同时让不同版本的应用各自依赖对应版本的共享库(主要用于测试场景)
  • 避免在CMake中硬编码库版本路径,防止Conan配置和CMake路径不一致导致的错误
  • 不依赖系统库路径,也不能使用容器方案

当前已尝试的CMake配置:

set_target_properties(app_one PROPERTIES
  INSTALL_RPATH "$ORIGIN/../lib"
)

该配置仅能应对单版本库的场景,无法满足多版本共存需求。


解决方案

1. Conan打包部署共享库与版本管理

  • 打包阶段:在库的conanfile.py中明确设置shared=True,确保生成共享库。利用Conan的包布局特性,默认会按包名/版本的结构组织库文件,无需手动修改package()方法的目录逻辑,Conan会自动维护版本隔离的基础结构。
  • 部署阶段:在目标机器上,通过Conan的install命令指定版本和独立安装目录,比如:
    conan install lib/0.0.1@user/channel --install-folder ./deploy/lib/lib_0.0.1
    conan install lib/0.0.2@user/channel --install-folder ./deploy/lib/lib_0.0.2
    
    让不同版本的库完全隔离在各自的目录中。
  • 动态链接路径配置:不要在CMake中硬编码版本,而是在应用的conanfile.py中,通过generate()方法注入依赖版本对应的RPATH路径。比如利用Conan的CMakeDeps生成工具,自动将依赖库的路径传递给CMake,最终生成类似$ORIGIN/../lib/lib_0.0.1的RPATH,全程由Conan根据依赖版本动态生成,避免人为错误。

2. 依赖共享库的应用打包

  • 应用依赖声明:在应用的conanfile.py中明确指定依赖库的版本,比如requires = "lib/0.0.1@user/channel",Conan会自动关联对应版本的共享库。
  • 打包与目录布局:使用conan create打包应用时,在package()方法中按版本隔离应用文件,推荐部署目录结构如下:
    deploy/
      app_1.0.0/
        bin/
          app_one
        lib/
          lib_0.0.1/
            libfoo.so
      app_1.1.0/
        bin/
          app_one
        lib/
          lib_0.0.2/
            libfoo.so
    
    每个应用版本自带对应版本的依赖库,RPATH设置为$ORIGIN/../lib/lib_<version>,运行时直接加载自身目录下的库,完全避免版本冲突。
  • 避免硬编码:通过Conan的CMakeToolchain传递RPATH变量,在CMake中直接使用${CMAKE_INSTALL_RPATH},无需手动写死版本字符串。

3. 环境维护与旧版本清理

  • 版本追踪:在部署机器上维护一个deploy_manifest.json清单文件,记录每个已部署的应用/库版本、安装路径、依赖关系,比如:
    {
      "app_1.0.0": {
        "path": "./deploy/app_1.0.0",
        "dependencies": ["lib/0.0.1"]
      },
      "lib_0.0.1": {
        "path": "./deploy/lib/lib_0.0.1",
        "used_by": ["app_1.0.0"]
      }
    }
    
  • 自动化清理:编写脚本定期执行以下操作:
    • 扫描部署目录的文件访问时间(atime),标记超过30天未被访问的版本
    • 对照清单文件,清理没有任何应用依赖的库版本
    • 提供交互式确认步骤,避免误删正在使用的版本
  • Conan缓存清理:使用conan remove命令清理本地缓存中不再需要的包版本,比如:
    conan remove "lib/0.0.1@user/channel" --confirm
    
    执行前需确认该版本未被任何已部署的应用依赖。

内容的提问来源于stack exchange,提问作者IvanYanakiev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 01:35:08