conan config set general.default_package_id_mode=full_version_mode 可全局修改 package ID 计算方式,影响后续 conan create/install;但不重算已有包 ID,需重新构建上传;单包可通过重写 package_id() 精细控制,如剔除 compiler.version 或声明 compatible_packages;private 依赖可避免被上层覆盖导致 ID 漂移。

conan config set general.default_package_id_mode 改全局模式
直接改默认计算方式,影响所有后续 conan create 或 conan install 产生的 package ID。常见取值有:semver_direct_mode(只看直接依赖的主版本号)、full_version_mode(连 patch 版本和间接依赖都参与计算)、recipe_revision_mode(源码变更即 ID 变)。
执行命令:
conan config set general.default_package_id_mode=full_version_mode
注意:这个设置不会 retroactively 重算已有包的 ID,只对新构建生效;如果远端已存在旧 ID 的二进制,切 mode 后 conan install 会找不到,必须重新 conan create 或上传。
在 conanfile.py 里重写 package_id() 控制单个包
比全局配置更精细,适合解决特定兼容性问题,比如 GCC 4.9 找不到二进制时 fallback 到 4.8。
常见操作包括:
- 用
self.info.requires["xxx"].full_package_mode()强制某个依赖参与全版本计算 - 用
self.compatible_packages.append(...)声明可替代的 package ID(如 Debug → Release) - 用
del self.info.settings.compiler.version把编译器版本从 ID 中剔除(慎用,ABI 可能不兼容) - 在
validate()里拒绝某些配置时,最好也在package_id()里排除对应组合,否则 Conan 仍会尝试匹配并浪费时间
requires 声明时加 'private' 避免依赖覆盖
当你的包依赖 opencv/2.4,但上层项目声明了 opencv/4.10,Conan 默认会让后者“覆盖”前者,导致 package ID 不一致、缓存失效、强制重编译——即使你只想用预编译二进制。
解决方法是在 requires 列表里显式标记为 private:
requires = [("opencv/2.4.13@user/stable", "private")]
这样该依赖不会被上层项目的同名 require 影响,ID 计算也只基于你声明的版本,不会因外部覆盖而漂移。
settings 和 options 的粒度决定 ID 分辨率
package ID 是 settings + options + requires 共同哈希的结果,但不是所有字段都默认参与:
-
build_type、os、arch、compiler天然进 ID;compiler.version是否参与取决于当前default_package_id_mode -
options如shared=True默认进 ID;但若在configure()里删掉某 option(del self.options.shared),它就不再影响 ID - 交叉编译时,
os.target和arch.target(而非 host)才决定最终 ID,这点容易忽略,尤其在嵌入式场景下
ID 规则本身不难改,难的是改完之后上下游二进制是否还能复用——一个看似微小的 del self.info.settings.compiler.libcxx 就可能让整个依赖图的缓存全部失效。

















