conan 默认不覆盖同 reference 下不同 package_id 的二进制包,只要 settings 或 options 不同(如 shared=true/false、compiler.cppstd=17/20)即并存;通过 user/channel 区分逻辑版本(如 @team/stable 与 @team/testing)可实现完全隔离;避免覆盖的关键是确保每次构建生成唯一 package_id,而非依赖手动保留。

conan install 时如何避免覆盖已有二进制包
Conan 默认不会覆盖本地缓存中已存在的二进制包,只要它们的 reference(如 zlib/1.2.13@user/channel)和 package_id(由 settings + options 唯一决定)不同,就会并存。关键不是“手动保留”,而是确保每次构建/导出时生成的 package_id 不冲突。
常见错误是反复用同一个 conan create . 命令、但没改 version 或 options,结果新包直接覆盖旧包——其实是因为 package_id 完全一致,Conan 认为这是同一份二进制。
- 检查当前缓存里是否真有多个版本:
conan list "zlib/*"或conan list "mylib/1.0.0@*" - 确认两个包的
package_id是否不同:conan list "mylib/1.0.0@user/testing" --graph=graph.html,然后打开 HTML 查看节点 ID - 若想强制生成新 package_id,可临时加一个无影响但能变 ID 的 option,比如
--options mylib:dev_build=True
用 version + user/channel 区分逻辑版本
Conan 的 reference 格式是 name/version@user/channel,其中 user 和 channel 是纯标识符,不参与 ABI 计算,但可用于组织生命周期。例如:
-
mylib/1.2.0@team/stable:正式发布版 -
mylib/1.2.0@team/testing:预发布验证版 -
mylib/1.2.0@ci/pr-42:CI 流水线为某 PR 构建的临时包
这些 reference 彼此完全独立,即使所有 settings 和 options 都一样,也会在缓存中并存。注意:如果上传到远程,需确保远程允许同名不同 channel 的上传(Artifactory 默认允许,conan_server 需配置)。
profile 和 settings 变动如何影响二进制共存
同一个 mylib/1.2.0@user/channel,只要 settings 或 options 有差异,就会生成不同 package_id 并共存。比如:
-
conan install . -pr=linux-gcc12-release→ 生成5ab3c9... -
conan install . -pr=linux-gcc12-debug→ 生成f8d2e1... -
conan install . -o mylib:shared=True→ 再生成一个新 ID
容易踩的坑:compiler.cppstd 改变(如从 17 → 20)会触发新 package_id,但某些旧版 CMakeLists.txt 若没正确传递 CXX_STANDARD,可能导致链接失败——此时二进制虽共存,却不可用。
清理时别误删其他版本
执行 conan remove 要格外小心。默认行为是按 reference 删除整个包(含所有二进制),不是按单个 package_id。
- 只删某个特定二进制:
conan remove "mylib/1.2.0@user/channel" -p=5ab3c9... - 删掉某个 reference 下所有二进制:
conan remove "mylib/1.2.0@user/channel" - 删掉所有匹配 pattern 的 reference:
conan remove "mylib/*"
真正容易被忽略的是:当你用 conan upload 到私有远程时,remote 默认不校验 package_id 是否已存在;若本地缓存里混着调试版和发布版,又没加 --force,upload 可能静默跳过部分二进制——得用 conan list 对比本地和 remote 的输出才能发现缺了哪几个。











