Conan 2.x 禁止在 [requires] 中重复声明同一库不同版本,需通过 profile 切换(如 -pr=myfmt9)、conf.get() 动态传入版本(如 -c "user.myproject:fmt_version=9.1.0")或封装为不同包名(如 fmt9::fmt)实现多版本隔离。

conan install 时怎么指定不同版本的同一库
Conan 允许你在同一个项目中声明多个版本的同一库,但必须明确隔离——它不会自动合并或覆盖。关键不是“同时用”,而是“按需选”。比如你既需要 fmt/10.2.1 给主逻辑用,又需要 fmt/9.1.0 测试兼容性,就得靠 conanfile.py 中的条件逻辑或子配置来区分。
常见错误是直接在 [requires] 里写两行:fmt/10.2.1 和 fmt/9.1.0,结果报错 ConanException: Duplicated requirement fmt。Conan 2.x 默认禁止重复 require 同一名称的包(哪怕版本不同)。
- 若真需多版本共存(如插件系统、运行时加载),应把它们封装成不同名字的 package:比如
fmt10::fmt和fmt9::fmt,通过self.cpp_info.set_property("cmake_target_name", "fmt10::fmt")在package_info()中重命名 - 更实际的做法是用
tool_requires隔离构建期依赖:比如用cmake/3.25.2构建时依赖旧版jsoncpp/1.9.5,而运行时依赖jsoncpp/2.10.0,两者互不干扰 - CI 场景下推荐用 profile 文件分环境:一个 profile 指定
fmt/10.2.1,另一个指定fmt/9.1.0,通过conan install . -pr=myfmt9切换
conanfile.py 里如何安全地切换同一库的版本
硬编码版本号(如 self.requires("fmt/10.2.1"))会导致每次改版本都要动代码。更灵活的方式是把版本提取为配置项,再由外部控制:
在 conanfile.py 中写:
def requirements(self):
fmt_version = self.conf.get("user.myproject:fmt_version", default="10.2.1")
self.requires(f"fmt/{fmt_version}")
然后安装时传入:
conan install . -c "user.myproject:fmt_version=9.1.0"
- 这个
conf是 Conan 2.x 的配置机制,比环境变量更可靠,且能被 profile 复用 - 注意
user.*命名空间是用户自定义的,避免和 Conan 内置 key 冲突 - 如果没设默认值,
conf.get()返回None,会直接 crash,所以务必加default=
CMake 中怎么避免 find_package 找混不同版本
Conan 生成的 *Config.cmake 文件默认按包名+版本号命名(如 fmtConfig.cmake),但 CMake 的 find_package(fmt) 不关心版本——它只找第一个匹配的 fmtConfig.cmake。如果你本地缓存里既有 fmt/10.2.1 又有 fmt/9.1.0,CMake 很可能找到旧的那个。
- 必须用
CMakeDeps生成器(不是cmake_find_package),它会为每个版本生成独立的fmt-10-2-1-config.cmake,并在conan_deps.cmake中按需 include - 在
CMakeLists.txt中显式指定版本约束:find_package(fmt 10.2.1 REQUIRED CONFIG),否则 CMake 会跳过版本检查 - 确保
CMAKE_PREFIX_PATH只包含当前 conan install 输出的目录(如${CMAKE_BINARY_DIR}),不要把全局~/.conan2加进去,否则会污染查找路径
缓存里存了多个版本,怎么清理不用的
Conan 不会自动删旧版本,长期积累会导致磁盘占用飙升,而且 conan search 结果越来越长,容易误选。
查有哪些版本:
conan search fmt
删指定版本:
conan remove "fmt/9.1.0" --force
-
conan remove "*"会清空整个缓存,慎用;更安全的是先conan list "fmt/*" --graph=build_graph.json看哪些版本正被项目引用 - 私有仓库场景下,
conan remove只影响本地缓存,不影响远程;删远程要用conan upload --delete(需权限) - CI 环境建议加
--no-cache参数跑conan install,避免污染共享缓存


















