Conan 2.x 中条件依赖必须在 conanfile.py 的 requirements() 方法内通过 self.settings 动态声明,不可写入 CMakeLists.txt;需配合 --profile:host 指定目标平台,使用 CMakeDeps + find_package(... CONFIG REQUIRED) 无条件链接,确保可重现性与跨平台一致性。

conanfile.py里用settings判断平台和编译器
条件依赖不是靠if写在CMakeLists.txt里,而是在conanfile.py中根据self.settings动态声明requires。Conan 2.x 不支持conanfile.txt做条件逻辑,必须升级到conanfile.py。
常见错误是把平台判断写进CMake,结果交叉编译时find_package()找不到库——因为依赖根本没被Conan下载或构建。
-
self.settings.os、self.settings.arch、self.settings.compiler是可靠依据;platform.system()等Python运行时检测不可靠(比如在Windows上交叉编译Linux目标) - 避免用
os.environ或命令行参数传平台信息,它们无法被Conan lock file捕获,导致可重现性断裂 - 条件块里调用
self.requires(),不要直接赋值self.requires = [...],后者不触发依赖图解析
def requirements(self):
if self.settings.os == "Windows":
self.requires("winpcap/4.1.3")
elif self.settings.os == "Linux":
self.requires("libpcap/1.10.4")
if self.settings.compiler == "gcc" and self.settings.compiler.version >= "12":
self.requires("stdexec/0.13")
profile隔离不同目标平台的构建配置
同一份conanfile.py要适配嵌入式ARM和桌面x86_64,不能靠硬编码判断,得靠--profile:host指定目标环境。profile才是Conan里“谁编、给谁编”的权威来源。
容易踩的坑是只用默认profile,或者把arch/os写死在conanfile.py里——这会让conan lock生成的锁文件失去跨平台意义。
- 为每个目标平台建独立profile文件,如
profiles/armv8-linux-gcc和profiles/x86_64-windows-msvc - profile里明确写
compiler.libcxx=libstdc++11或compiler.runtime=MD,这些setting会参与二进制ID计算,影响条件依赖是否命中 - 执行
conan install时显式带--profile:host=profiles/armv8-linux-gcc,别依赖自动detect
options控制库的内部行为分支
有些库本身提供编译开关(比如openssl是否启用zlib压缩),这些不是平台条件,而是功能选配,应通过self.options暴露并传递,而不是在requirements()里重复声明。
典型误操作:看到zlib被openssl依赖,就手动self.requires("zlib/1.3.1")——这会导致两套zlib ABI冲突,尤其当一个静态一个动态时。
- 优先查目标库文档,看它是否原生支持
with_zlib=True这类option - 用
self.options["openssl"].with_zlib = True开启,Conan会自动拉取并协调zlib版本 - 若必须覆盖子依赖的option(比如强制所有库用
shared=True),用-o *:shared=True命令行参数,而非在conanfile.py里硬写
CMakeLists.txt里不写条件find_package
一旦用了CMakeDeps + CMakeToolchain,CMake侧就该彻底放弃if(WIN32) find_package(...)这种写法。Conan已按profile生成了对应平台的*Config.cmake,CMake只需无条件find_package(XXX CONFIG REQUIRED)。
否则会出现:本地Windows构建成功,CI里Linux跑conan install --profile:host=linux后,CMake仍试图找Windows版FindXXX.cmake,报Could not find a package configuration file。
-
find_package()调用必须带CONFIG关键字,否则会 fallback 到旧式FindXXX.cmake搜索路径,绕过Conan生成的配置 - 所有target_link_libraries都用
XXX::XXX别名(如fmt::fmt),别用XXX_LIBRARIES变量,后者不跨平台 - 如果某个库只在特定平台存在(如
winmm),让它在conanfile.py里条件requires,CMake里仍写find_package(winmm CONFIG REQUIRED)——Conan会在不匹配平台时静默跳过该require,生成的config文件自然不存在,CMake报错反而是你漏写了条件逻辑的信号
if self.settings.os == "...",而是确保每个self.requires()调用背后,对应的profile setting、option取值、以及CMake消费方式三者严格对齐。差一个字符(比如libstdc++漏写11),二进制缓存就失效,条件逻辑就白写。

















