conan.lock是跨平台构建的强制前提,因其基于完整构建维度生成package ID,确保不同平台解析出完全一致的依赖二进制,避免ABI不兼容、链接失败等隐性问题。

要,而且必须用 conan.lock —— 否则跨平台构建大概率在某台机器上突然失败,且你很难复现。
为什么 conan.lock 不是“可选”,而是跨平台的强制前提
Conan 的依赖解析不是纯版本号匹配,而是基于完整构建维度(os、arch、compiler、build_type、compiler.version 等)生成 package ID。同一份 conanfile.txt 在 macOS 上解析出的 OpenSSL 包 ID,和在 Windows MSVC 2019 上解析出的,几乎必然不同。
如果没有 conan.lock,每次 conan install 都会重新解析远程仓库,可能拿到:
- 不同编译器版本下预编译的二进制(比如 Linux GCC 11 vs GCC 12 生成的 fmt ABI 不兼容)
- 同一库但不同 shared/static 选项的包(zlib/*:shared=True 在 Windows 上默认不启用,Linux 上可能默认启用)
- 甚至因远程仓库更新导致某个子依赖被升级(如 openssl/3.2.1 → openssl/3.3.0),而新版本尚未提供你目标平台的二进制
这些差异不会报错,但会在链接阶段或运行时暴露:undefined reference、DLL load failure、segmentation fault。
conan.lock 怎么生成和更新才安全
它不是手动写的,也不能靠“本地能跑就 commit”。正确流程是:
- 首次生成:用
conan install . --lockfile-out=conan.lock(显式指定输出,避免隐式行为) - CI/CD 中必须加
--lockfile参数:例如conan install . --lockfile=conan.lock --build=missing,否则锁文件形同虚设 - 更新依赖时,不要直接改
conanfile.txt后重装 —— 先用conan lock update conan.lock --requires="fmt/10.2.0"更新锁文件,再验证 - 团队协作时,
conan.lock必须提交进 Git;忽略它 = 放弃跨平台一致性保障
常见误用:以为 profile 能替代 lockfile
有人觉得只要统一 -pr:h linux_gcc12_release 就够了。错。profile 只控制“我要什么”,不保证“我能拿到什么”。实际构建时 Conan 仍会按 profile 去远端查可用二进制 —— 而远端是否真有那个 exact package ID,只有 conan.lock 记录过才能确认。
典型错误现象:
- 本地
conan install成功,CI 报ERROR: Missing binary: xxx/1.2.3@user/channel - Windows 开发者用 VS2022 构建成功,Linux CI 用 GCC 12 失败,报
undefined symbol: SSL_CTX_set_ciphersuites -
conan list显示所有依赖都已安装,但cmake --build链接失败,提示找不到libfmt.a对应的架构变体
这些问题背后,90% 是因为 conan.lock 没生效、没提交、或没在 CI 中使用。
锁文件不是银弹:它只锁住“解析结果”,不锁住“构建逻辑”
conan.lock 固定的是每个依赖的 package ID 和哈希,但它不阻止以下情况:
- 你本地修改了某个依赖的
conanfile.py配方,却没更新revision字段 → 锁文件仍指向旧 revision,但本地构建用了新逻辑 - 某个依赖的二进制是本地
--build=missing编译的,而 CI 没开该选项 → 锁文件一致,但实际二进制内容不一致 -
conan.lock中记录的build_type=Debug,但 CMake 被误设为Release→ 链接时符号不匹配,错误直到运行时才暴露
所以真正跨平台可靠的组合是:conan.lock + 统一 profile + CI 中强制 --build=missing 或明确禁用(视策略而定)+ 构建前校验 conan list 输出与锁文件一致。


















