conan 不支持在 conanfile.py 中直接用 if/else 切换编译选项,必须在 configure() 阶段通过 self.settings.os(如 "linux"、"windows")条件修改 self.options,以确保依赖图一致性;推荐将系统差异下沉至 profile 的 [conf] 段统一配置 cmake 变量或编译标志,而非硬编码逻辑。

conanfile.py 中用 settings.os 判断系统类型
Conan 不支持在 conanfile.py 里写 if/else 直接切换编译选项,但可以通过 configure() 或 layout() 阶段读取 self.settings.os 做条件分支。关键点是:必须在 configure() 中修改 self.options,不能在 build() 里改——否则会导致依赖图不一致。
常见错误现象:conan install 成功,但 conan build 报错说某个 option 未定义,或链接失败,就是因为编译选项没在 configure 阶段“声明好”。
-
self.settings.os可取值为"Linux"、"Windows"、"Macos"、"FreeBSD"等,大小写敏感 - 嵌入式场景下可能为
"baremetal"或自定义值,需和 profile 里[settings]严格一致 - 不要用
platform.system(),那是 Python 运行时宿主系统,不是目标系统
profile 中用 [conf] 按系统注入 CMake 变量
更推荐的方式是把系统差异下沉到 profile,而不是硬编码在 conanfile.py 里。通过 [conf] 段落设置 tools.cmake.cmaketoolchain:user_toolchain 或直接传 CMake 变量,能解耦逻辑、复用 profile。
例如,在 Linux profile 中加:
[conf]
tools.cmake.cmaketoolchain:extra_variables={"LINUX_ONLY_FLAG": "ON"}
在 Windows profile 中加:
[conf]
tools.cmake.cmaketoolchain:extra_variables={"WIN32_ONLY_FLAG": "ON"}
这样 CMakeLists.txt 里就能用 if(WIN32_ONLY_FLAG) 或 target_compile_definitions(... PRIVATE WIN32_ONLY),而 conanfile.py 完全不用动。
-
[conf]的值会转成 CMake 的-D参数,自动生效于CMakeToolchain生成阶段 - 如果要用
add_definitions()级别宏,建议统一走tools.build:defines,它对所有构建工具都有效 - 注意:CMakeToolchain v0.10+ 才支持
extra_variables,旧版得靠user_toolchain文件中手写set(... CACHE INTERNAL "")
tools.build:cxxflags 按系统配置编译器标志
不同系统常用标志差异大:Linux 常用 -fPIC 和 -D_GNU_SOURCE,Windows MinGW 需要 -D_WIN32,macOS 要 -mmacosx-version-min=11.0。这些不该写死在 conanfile.py,而应由 profile 控制。
示例(Linux profile):
[conf] tools.build:cxxflags=["-fPIC", "-D_GNU_SOURCE"] tools.build:cflags=["-fPIC", "-D_GNU_SOURCE"]
示例(Windows MinGW profile):
[conf] tools.build:cxxflags=["-D_WIN32", "-D__USE_MINGW_ANSI_STDIO"] tools.build:cflags=["-D_WIN32", "-D__USE_MINGW_ANSI_STDIO"]
- 这些 flag 会透传给底层构建系统(CMake/Autotools/Meson),无需在
conanfile.py中拼接 - 如果同时用
tools.build:defines和tools.build:cxxflags,后者优先级更高,会覆盖前者定义的同名宏 - 交叉编译时,
tools.build:cxxflags里的 flag 仍作用于目标平台,不是宿主机;别误加-m64这类宿主相关 flag
避免用 self.settings.os == "Windows" 做运行时判断
有人会在 build() 方法里写 if self.settings.os == "Windows": run("cl.exe ..."),这看似直观,实则危险:Conan 的依赖解析、二进制兼容性检查都基于 settings,但 build() 是执行阶段,此时已错过约束校验时机。
真正该做的是:
- 用
[tool_requires]在 profile 里声明平台专用构建工具(如ninja/1.12.1for Linux,msbuild/17.0for Windows) - 让
CMake或AutotoolsBuildEnvironment自动适配命令,而不是自己调run() - 若真需平台特有命令(比如注册 COM 组件),应封装成独立的
deploy()步骤,且明确标注if self.settings.os == "Windows"是部署逻辑,非构建逻辑
最易被忽略的一点:profile 中的 os 是目标系统,不是你当前 conan install 所在的机器。交叉编译时,self.settings.os 来自 profile,不是 uname -s。这点一旦搞混,整个条件分支就全错。











