Conan/CMake编译VS2017 DLL需VC++运行库问题求解
这个问题我之前帮不少开发者解决过,核心原因是Conan的默认配置和你直接用VS新建项目的设置不一致,尤其是C/C++运行时库(CRT)的链接方式在两者间有差异。咱们一步步来解决:
1. 修正Conan Profile的运行时库设置
Conan的Profile会直接覆盖CMake的编译器选项,这是很多人忽略的关键点。你需要确保你的Conan Profile指定了静态链接CRT(也就是MT/MTd),而非默认的动态链接(MD/MDd):
- 找到你的Conan Profile文件(通常在
%USERPROFILE%\.conan\profiles目录下,或者自定义路径) - 在Profile的
[settings]部分添加或修改:[settings] compiler=msvc compiler.version=15 # VS2017对应的版本号是15 compiler.runtime=MT # Release模式用MT,Debug模式替换为MTd - 建议为Debug和Release分别创建独立的Profile,避免切换模式时出错。
2. 在CMakeLists.txt中强制锁定运行时库
即使Conan设置了Profile,有时候CMake的默认配置可能会“跑偏”,所以最好在CMake脚本里明确指定运行时库,确保和Conan的设置完全一致:
# 针对Release模式 set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT") set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /MT") # 针对Debug模式 set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd") set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /MTd")
注意:这段代码要放在Conan配置脚本(比如
conan_basic_setup())之后执行,避免被Conan的设置覆盖。
3. 检查并重新构建依赖包
如果你的项目依赖了其他Conan包,这些包本身可能是用动态CRT(MD)编译的,会强制你的项目也使用动态链接,进而导致需要VC++可再发行组件。解决方法:
- 执行
conan install时加上--build=missing参数,让Conan根据你的Profile设置重新编译所有依赖包,确保它们都用MT/MTd链接CRT:conan install . -s compiler.runtime=MT --build=missing - 如果你用的是Conan 2.x,命令调整为:
conan install . -s:b compiler.runtime=MT -s:h compiler.runtime=MT --build=missing
4. 禁用CLR/ZW相关选项
你提到试过/clr和/ZW选项——这些是针对.NET/Windows Runtime的编译选项,它们强制要求使用动态CRT(因为CLR本身依赖动态链接的运行时)。如果你的DLL不需要支持.NET或UWP,一定要彻底关闭这些选项:
- 在CMakeLists.txt里确保没有设置
CMAKE_CXX_FLAGS包含/clr或/ZW - 生成VS工程后,检查项目属性:在「C/C++ -> 常规」里,确认「公共语言运行时支持」设为「无」,「Windows运行时扩展」设为「否」
5. 验证最终链接配置
最后,你可以生成VS工程后,检查项目属性确认配置正确:
- 打开「C/C++ -> 代码生成」,查看「运行时库」选项:Release应为「多线程(/MT)」,Debug应为「多线程调试(/MTd)」
- 查看「链接器 -> 输入 -> 附加依赖项」:确保没有
msvcrt.lib(动态CRT),而是libcmt.lib(静态CRT)
因为VS新建项目时,默认的运行时库设置可能是你习惯的MT/MTd(或者你手动改过),而Conan的默认Profile通常用MD/MDd(动态链接CRT),这就导致了差异——动态链接CRT的DLL必须依赖VC++可再发行组件,而静态链接的则不需要。
内容的提问来源于stack exchange,提问作者programerC

