我在集成开源 OpenCV 的图像质量评估功能时碰到一个运行时库问题。
win32平台开发需要:
- 先用 CMake 源码生成 VS2017 win32 静态库工程 (优先使用开源项目的静态库lib)
- 然后将OpenCV静态库的接口封装成一个DLL
- 最后将封装后DLL集成到项目中
但在第2步生成DLL时链接报错:
bash
1>------ 已启动生成: 项目: xxxcv, 配置: Release Win32 ------
1>opencv_world4130.lib(mean.dispatch.obj) : error LNK2038: 检测到"RuntimeLibrary"的不匹配项: 值"MT_StaticRelease"不匹配值"MD_DynamicRelease"(cloopbuffer.obj 中)
1>opencv_world4130.lib(calibinit.obj) : error LNK2038: 检测到"RuntimeLibrary"的不匹配项: 值"MT_StaticRelease"不匹配值"MD_DynamicRelease"(cloopbuffer.obj 中)
1>opencv_world4130.lib(calibration.obj) : error LNK2038: 检测到"RuntimeLibrary"的不匹配项: 值"MT_StaticRelease"不匹配值"MD_DynamicRelease"(cloopbuffer.obj 中)
1>opencv_world4130.lib(out.obj) : error LNK2038: 检测到"RuntimeLibrary"的不匹配项: 值"MT_StaticRelease"不匹配值"MD_DynamicRelease"(cloopbuffer.obj 中)
1>opencv_world4130.lib(loadsave.obj) : error LNK2038: 检测到"RuntimeLibrary"的不匹配项: 值"MT_StaticRelease"不匹配值"MD_DynamicRelease"(cloopbuffer.obj 中)
1>opencv_world4130.lib(thresh.obj) : error LNK2038: 检测到"RuntimeLibrary"的不匹配项: 值"MT_StaticRelease"不匹配值"MD_DynamicRelease"(cloopbuffer.obj 中)
1>opencv_world4130.lib(cornersubpix.obj) : error LNK2038: 检测到"RuntimeLibrary"的不匹配项: 值"MT_StaticRelease"不匹配值"MD_DynamicRelease"(cloopbuffer.obj 中)
1>opencv_world4130.lib(matrix.obj) : error LNK2038: 检测到"RuntimeLibrary"的不匹配项: 值"MT_StaticRelease"不匹配值"MD_DynamicRelease"(cloopbuffer.obj 中)
1>opencv_world4130.lib(convert.dispatch.obj) : error LNK2038: 检测到"RuntimeLibrary"的不匹配项: 值"MT_StaticRelease"不匹配值"MD_DynamicRelease"(cloopbuffer.obj 中)
1>opencv_world4130.lib(color.obj) : error LNK2038: 检测到"RuntimeLibrary"的不匹配项: 值"MT_StaticRelease"不匹配值"MD_DynamicRelease"(cloopbuffer.obj 中)
1>opencv_world4130.lib(matrix_wrap.obj) : error LNK2038: 检测到"RuntimeLibrary"的不匹配项: 值"MT_StaticRelease"不匹配值"MD_DynamicRelease"(cloopbuffer.obj 中)
1>opencv_world4130.lib(system.obj) : error LNK2038: 检测到"RuntimeLibrary"的不匹配项: 值"MT_StaticRelease"不匹配值"MD_DynamicRelease"(cloopbuffer.obj 中)
1>opencv_world4130.lib(deriv.obj) : error LNK2038: 检测到"RuntimeLibrary"的不匹配项: 值"MT_StaticRelease"不匹配值"MD_DynamicRelease"(cloopbuffer.obj 中)
1>opencv_world4130.lib(norm.dispatch.obj) : error LNK2038: 检测到"RuntimeLibrary"的不匹配项: 值"MT_StaticRelease"不匹配值"MD_DynamicRelease"(cloopbuffer.obj 中)
......
❌ 问题:运行时库(Runtime Library)不匹配
error LNK2038: 检测到"RuntimeLibrary"的不匹配项: 值"MT_StaticRelease"不匹配值"MD_DynamicRelease"
🔍 原因:
- OpenCV 静态库
opencv_world4130.lib是用 /MT(静态链接运行时库)编译的。 - 而你的项目
cloopbuffer.obj是用 /MD(动态链接运行时库)编译的。 - Visual Studio 不允许混合使用 /MT 和 /MD,因为它们使用不同的 C 运行时(CRT)。
✅ 解决方案:
统一运行时库选项。
下面有两种改法:
方案 1:将你的项目改为使用 /MT
- 在 Visual Studio 中右键你的项目 → 属性(Properties)
- 进入 C/C++ → Code Generation
- 将 Runtime Library 设置为:
- Release 模式 :
Multi-threaded (/MT) - Debug 模式 :
Multi-threaded Debug (/MTd)
- Release 模式 :
⚠️ 注意:如果你的项目依赖其他第三方库,也要确保它们也是用 /MT 编译的,否则会再次出现类似冲突。
方案 2:重新编译 OpenCV 使用 /MD
如果你不想改自己的项目设置(比如你必须用 /MD),那么你需要:
- 从源码重新编译 OpenCV,并在 CMake 配置时指定 /MD
💡 OpenCV 官方预编译的
opencv_world4130.lib默认是 /MT 的(尤其是 static 版本),所以大多数情况下建议你改自己的项目为 /MT。
🔧 补充:如何确认 lib 的编译方式?
你可以用 dumpbin 查看 .lib 文件的编译选项:
cmd
dumpbin /directives xxx.lib | findstr "RuntimeLibrary"
或者用工具如 Dependency Walker 或 Visual Studio 的 lib 工具。
项目其他组件库都是 /MD ,所以我只能选择 "方案2 重新编译 OpenCV 使用 /MD"
重新编译 OpenCV 使用 /MD
我再重编 OpenCV 时,使用了许多方法来指定 /MD ,但都失败了,结果都是 /MT
失败举例:
- 使用 CMake 配置选项
DCMAKE_MSVC_RUNTIME_LIBRARY="MultiThreadedDLL"
bash
cmake -G "Visual Studio 15 2017" -A Win32 \
-DCMAKE_MSVC_RUNTIME_LIBRARY="MultiThreadedDLL" \
......
- 使用 OpenCV 提供的专用选项
OPENCV_LINK_RUNTIMEDYNAMIC
bash
cmake -G "Visual Studio 15 2017" -A Win32 \
-D CMAKE_BUILD_TYPE=Release \
-D OPENCV_LINK_RUNTIMEDYNAMIC=ON \
-D BUILD_SHARED_LIBS=ON \
......
- CMake 同时使用两个变量(双重保险)
bash
cmake -G "Visual Studio 15 2017" -A Win32 \
-D CMAKE_MSVC_RUNTIME_LIBRARY="MultiThreadedDLL" \
-D OPENCV_LINK_RUNTIMEDYNAMIC=ON \
-D BUILD_SHARED_LIBS=ON \
......
- 在 CMake 命令行中显式清除 /MT 并注入 /MD
bash
cmake -G "Visual Studio 15 2017" -A Win32 ^
-D CMAKE_BUILD_TYPE=Release ^
-D BUILD_SHARED_LIBS=OFF ^
-D OPENCV_LINK_RUNTIMEDYNAMIC=ON ^
-D CMAKE_MSVC_RUNTIME_LIBRARY="MultiThreadedDLL" ^
-D CMAKE_CXX_FLAGS_RELEASE="/MD -Ob2 -Oi -O2" ^
-D CMAKE_C_FLAGS_RELEASE="/MD -Ob2 -Oi -O2" ^
-D CMAKE_CXX_FLAGS_DEBUG="/MDd -Zi -Ob0 -Od" ^
-D CMAKE_C_FLAGS_DEBUG="/MDd -Zi -Ob0 -Od" ^
......
- 用 msbuild 覆盖项目属性(强制指定 /MD)
即使OpenCV VS2017项目文件原本是 /MDd 或 /MT,你也可以在 msbuild 命令行中覆盖 RuntimeLibrary 属性
bash
msbuild opencv.sln /p:Configuration=Release /p:Platform=Win32 ^
/p:RuntimeLibrary=MultiThreadedDLL
但是以上所有方案全都失败了!
🔍 推测失败原因:
OpenCV 在其他地方(如 OpenCVUtils.cmake 或 OpenCVMinDepVersions.cmake)或通过 CMake 的默认行为设置了 /MT。
- OpenCV 其他脚本注入
/MT| 显式覆盖 `CMAKE_CXX_FLAGS_*
🛠️ 建议:查找真正的 /MT 注入点
在 OpenCV 源码中全局搜索:
bash
grep -r "/MT" cmake/
grep -r "MultiThreaded[^D]" cmake/
重点关注:
cmake/OpenCVUtils.cmakecmake/OpenCVMinDepVersions.cmakeCMakeLists.txt
查找结果1:
OpenCVCRTLinkage.cmake 文件中:
bash
if(NOT BUILD_SHARED_LIBS AND BUILD_WITH_STATIC_CRT)
if(MSVC_RUNTIME_SET_BY_ABSTRACTION STREQUAL "NEW")
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
else()
foreach(flag_var
CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE
CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO
CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
if(${flag_var} MATCHES "/MD")
string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
endif()
if(${flag_var} MATCHES "/MDd")
string(REGEX REPLACE "/MDd" "/MTd" ${flag_var} "${${flag_var}}")
endif()
endforeach(flag_var)
endif()
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /NODEFAULTLIB:atlthunk.lib")
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} /NODEFAULTLIB:libcmt.lib /NODEFAULTLIB:libcpmt.lib /NODEFAULTLIB:msvcrt.lib")
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /NODEFAULTLIB:libcmtd.lib /NODEFAULTLIB:libcpmtd.lib /NODEFAULTLIB:msvcrtd.lib")
else()
if(NOT MSVC_RUNTIME_SET_BY_ABSTRACTION STREQUAL "NEW")
foreach(flag_var
CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE
CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO
CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
if(${flag_var} MATCHES "/MT")
string(REGEX REPLACE "/MT" "/MD" ${flag_var} "${${flag_var}}")
endif()
if(${flag_var} MATCHES "/MTd")
string(REGEX REPLACE "/MTd" "/MDd" ${flag_var} "${${flag_var}}")
endif()
endforeach(flag_var)
endif()
endif()
上面提供完整的 OpenCVCRTLinkage.cmake 逻辑!现在我们可以100% 精准定位问题并给出终极解决方案。
🔍 问题本质(结合你提供的完整逻辑)
该文件的核心逻辑如下:
cmake
if(NOT BUILD_SHARED_LIBS AND BUILD_WITH_STATIC_CRT)
# → 强制使用 /MT(静态 CRT)
else()
# → 强制使用 /MD(动态 CRT) ← 这才是你要的路径!
endif()
✅ 关键结论:
要让 OpenCV 静态库(
BUILD_SHARED_LIBS=OFF)使用/MD,必须确保BUILD_WITH_STATIC_CRT=OFF。
否则,程序会进入第一个 if 分支,无论你是否设置了 CMAKE_MSVC_RUNTIME_LIBRARY 或 OPENCV_LINK_RUNTIMEDYNAMIC=ON,都会被强制覆盖为 /MT。
🧩 为什么 -D OPENCV_LINK_RUNTIMEDYNAMIC=ON 可能失效?
在 OpenCV 中,OPENCV_LINK_RUNTIMEDYNAMIC 的作用通常是:
cmake
# 在某处(如 CMakeLists.txt)有类似逻辑:
if(DEFINED OPENCV_LINK_RUNTIMEDYNAMIC)
set(BUILD_WITH_STATIC_CRT ${OPENCV_LINK_RUNTIMEDYNAMIC} EQUAL 0)
endif()
但 如果这个映射发生在 OpenCVCRTLinkage.cmake 被包含之后 ,或者变量作用域有问题,BUILD_WITH_STATIC_CRT 仍可能保持默认值 ON。
因此,最可靠的方式是直接设置 BUILD_WITH_STATIC_CRT=OFF,绕过中间层。
✅ 终极解决方案:正确 CMake 命令
bat
cmake -G "Visual Studio 15 2017" -A Win32 ^
-D CMAKE_BUILD_TYPE=Release ^
-D BUILD_SHARED_LIBS=OFF ^
-D BUILD_WITH_STATIC_CRT=OFF ^ ← ⭐ 必须显式关闭!
-D CMAKE_MSVC_RUNTIME_LIBRARY="MultiThreadedDLL" ^
-D CMAKE_POLICY_DEFAULT_CMP0091=NEW ^
<opencv_source_path>
参数说明:
| 参数 | 作用 |
|---|---|
-D BUILD_SHARED_LIBS=OFF |
构建静态库(.lib) |
-D BUILD_WITH_STATIC_CRT=OFF |
关键! 禁用 /MT,走 else() 分支 → 使用 /MD |
-D CMAKE_MSVC_RUNTIME_LIBRARY="MultiThreadedDLL" |
CMake ≥3.15 标准方式,与新策略兼容 |
-D CMAKE_POLICY_DEFAULT_CMP0091=NEW |
启用 CMake 新的运行时库抽象机制 |
🔎 验证是否成功
配置完成后,检查以下两点:
1. CMakeCache.txt 中:
txt
BUILD_WITH_STATIC_CRT:BOOL=OFF
2. 生成的 .vcxproj 文件中(任一项目):
xml
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> <!-- Release -->
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> <!-- Debug -->
💡 如果看到
MultiThreaded(无 DLL),说明仍走了/MT分支,BUILD_WITH_STATIC_CRT未生效。
⚠️ 特别注意:else() 分支中的 /MT → /MD 替换
你提供的 else() 分支中有这段代码:
cmake
if(NOT MSVC_RUNTIME_SET_BY_ABSTRACTION STREQUAL "NEW")
foreach(flag_var ...)
if(${flag_var} MATCHES "/MT")
string(REGEX REPLACE "/MT" "/MD" ...)
endif()
endforeach()
endif()
这意味着:
- 如果你使用 CMake < 3.15 (
CMP0091未启用),OpenCV 会主动把 flags 中的/MT改成/MD。 - 但如果初始 flags 是空的,或已经是
/MD,则无需替换。 - 但在你的场景中,我们希望走这个
else()分支,并且最好配合CMAKE_MSVC_RUNTIME_LIBRARY(CMake ≥3.15)以避免字符串替换的不确定性。
📌 最佳实践总结
| 场景 | 推荐配置 |
|---|---|
静态库 + /MD(你的需求) |
-D BUILD_SHARED_LIBS=OFF -D BUILD_WITH_STATIC_CRT=OFF |
静态库 + /MT(默认) |
不设置 BUILD_WITH_STATIC_CRT(默认 ON) |
| 动态库(.dll) | -D BUILD_SHARED_LIBS=ON(此时 BUILD_WITH_STATIC_CRT 默认 OFF,用 /MD) |
✅ 记住:
BUILD_WITH_STATIC_CRT是控制/MTvs/MD的总开关,优先级高于其他变量。
🔚 附加建议
如果你仍然遇到问题,请在 CMake 配置输出中搜索:
txt
BUILD_WITH_STATIC_CRT
确认其值是否为 OFF。如果仍是 ON,说明命令行参数未传入成功(检查拼写、缓存等)。
也可以先清理构建目录:
bat
rd /s /q build
mkdir build
cd build
cmake -G ...(完整命令)
这样可避免 CMake 缓存旧值。
查找结果2:
在 CMakeLists.txt 文件中:
bash
# OpenCV build components
# ===================================================
OCV_OPTION(BUILD_SHARED_LIBS "Build shared libraries (.dll/.so) instead of static ones (.lib/.a)" NOT (ANDROID OR APPLE_FRAMEWORK) )
OCV_OPTION(BUILD_opencv_apps "Build utility applications (used for example to train classifiers)" (NOT ANDROID AND NOT WINRT) IF (NOT APPLE_FRAMEWORK) )
OCV_OPTION(BUILD_opencv_js "Build JavaScript bindings by Emscripten" OFF )
OCV_OPTION(BUILD_ANDROID_PROJECTS "Build Android projects providing .apk files" ON IF ANDROID )
OCV_OPTION(BUILD_ANDROID_EXAMPLES "Build examples for Android platform" ON IF ANDROID )
OCV_OPTION(BUILD_DOCS "Create build rules for OpenCV Documentation" OFF IF (NOT WINRT AND NOT APPLE_FRAMEWORK))
OCV_OPTION(BUILD_EXAMPLES "Build all examples" OFF )
OCV_OPTION(BUILD_PACKAGE "Enables 'make package_source' command" ON IF NOT WINRT)
OCV_OPTION(BUILD_PERF_TESTS "Build performance tests" NOT INSTALL_CREATE_DISTRIB IF (NOT APPLE_FRAMEWORK) )
OCV_OPTION(BUILD_TESTS "Build accuracy & regression tests" NOT INSTALL_CREATE_DISTRIB IF (NOT APPLE_FRAMEWORK) )
OCV_OPTION(BUILD_WITH_DEBUG_INFO "Include debug info into release binaries ('OFF' means default settings)" OFF )
OCV_OPTION(BUILD_WITH_STATIC_CRT "Enables use of statically linked CRT for statically linked OpenCV" ON IF MSVC )
OCV_OPTION(BUILD_WITH_DYNAMIC_IPP "Enables dynamic linking of IPP (only for standalone IPP)" OFF )
OCV_OPTION(BUILD_FAT_JAVA_LIB "Create Java wrapper exporting all functions of OpenCV library (requires static build of OpenCV modules)" ANDROID IF NOT BUILD_SHARED_LIBS)
OCV_OPTION(BUILD_ANDROID_SERVICE "Build OpenCV Manager for Google Play" OFF IF ANDROID )
OCV_OPTION(BUILD_CUDA_STUBS "Build CUDA modules stubs when no CUDA SDK" OFF IF (NOT APPLE_FRAMEWORK) )
OCV_OPTION(BUILD_JAVA "Enable Java support" (ANDROID OR NOT CMAKE_CROSSCOMPILING) IF (ANDROID OR (NOT APPLE_FRAMEWORK AND NOT WINRT)) )
OCV_OPTION(BUILD_OBJC "Enable Objective-C support" ON IF APPLE_FRAMEWORK )
OCV_OPTION(BUILD_KOTLIN_EXTENSIONS "Build Kotlin extensions (Android)" ON IF ANDROID )
上面提供 CMakeLists.txt 中关于构建选项的关键片段!现在我们可以彻底、精准地解释为什么你的 OpenCV 静态库工程仍然使用 /MT,以及如何 100% 可靠地切换到 /MD。
🔥 核心问题定位(基于你提供的代码)
在 CMakeLists.txt 中,有这一行:
cmake
OCV_OPTION(BUILD_WITH_STATIC_CRT "Enables use of statically linked CRT for statically linked OpenCV" ON IF MSVC )
✅ 关键解读:
- 默认值:
ON - 生效条件:
IF MSVC→ 在 Windows + Visual Studio 下总是生效 - 作用对象:即使你构建的是静态库(
BUILD_SHARED_LIBS=OFF),它也会启用静态 CRT(即/MT)
📌 这就是你所有问题的根源!
OpenCV 在 MSVC 平台下默认为静态库启用
/MT,这是设计行为,不是 bug。
✅ 正确解决方案(终极版)
要让 OpenCV 静态库使用 动态 CRT(/MD) ,你必须显式覆盖这个默认值:
bat
cmake -G "Visual Studio 15 2017" -A Win32 ^
-D BUILD_SHARED_LIBS=OFF ^
-D BUILD_WITH_STATIC_CRT=OFF ^ ← ⭐ 这是唯一关键参数!
<other options...>
path\to\opencv-source
为什么其他参数不够?
| 参数 | 是否足够? | 原因 |
|---|---|---|
-D OPENCV_LINK_RUNTIMEDYNAMIC=ON |
❌ 不一定 | 它可能只是 BUILD_WITH_STATIC_CRT=OFF 的别名,但在某些版本中映射不及时 |
-D CMAKE_MSVC_RUNTIME_LIBRARY="MultiThreadedDLL" |
❌ 不够 | OpenCV 的 OpenCVCRTLinkage.cmake 会先于 CMake 抽象机制强制覆盖 flags |
-D BUILD_WITH_STATIC_CRT=OFF |
✅ 足够且必要 | 直接关闭 OpenCV 的 /MT 强制逻辑,走 else() 分支 → 使用 /MD |
🔍 内部机制详解(结合你之前提供的文件)
-
CMakeLists.txt设置默认值:cmakeOCV_OPTION(BUILD_WITH_STATIC_CRT ... ON IF MSVC)→ 在 MSVC 下,
BUILD_WITH_STATIC_CRT=ON(除非你覆盖) -
OpenCVCRTLinkage.cmake执行逻辑:cmakeif(NOT BUILD_SHARED_LIBS AND BUILD_WITH_STATIC_CRT) # 强制 /MT else() # 强制 /MD ← 你要进这里! endif() -
只有当你设置
-D BUILD_WITH_STATIC_CRT=OFF,才会进入else()分支,从而:- 如果 CMake ≥ 3.15 + CMP0091=NEW → 使用
CMAKE_MSVC_RUNTIME_LIBRARY - 否则 → 主动将 flags 中的
/MT替换为/MD
- 如果 CMake ≥ 3.15 + CMP0091=NEW → 使用
✅ 推荐完整命令(VS2017 Win32 静态库 + /MD)
bat
cmake -G "Visual Studio 15 2017" -A Win32 ^
-D CMAKE_BUILD_TYPE=Release ^
-D BUILD_SHARED_LIBS=OFF ^
-D BUILD_WITH_STATIC_CRT=OFF ^
-D CMAKE_MSVC_RUNTIME_LIBRARY="MultiThreadedDLL" ^
-D CMAKE_POLICY_DEFAULT_CMP0091=NEW ^
-D BUILD_EXAMPLES=OFF ^
-D BUILD_TESTS=OFF ^
opencv-source
💡 即使不加
CMAKE_MSVC_RUNTIME_LIBRARY和CMP0091,只要BUILD_WITH_STATIC_CRT=OFF,OpenCV 也会通过字符串替换确保使用/MD。但加上更规范(尤其 CMake ≥3.15)。
🔎 验证步骤
-
检查 CMake 输出:
txt-- Static CRT: NO(如果显示
YES,说明BUILD_WITH_STATIC_CRT=ON仍生效) -
检查
CMakeCache.txt:txtBUILD_WITH_STATIC_CRT:BOOL=OFF -
检查生成的
.vcxproj:xml<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
📌 总结
| 问题 | 答案 |
|---|---|
为什么设置了 /MD 还是 /MT? |
因为 BUILD_WITH_STATIC_CRT 默认为 ON(MSVC 下) |
| 最关键的 CMake 参数是什么? | -D BUILD_WITH_STATIC_CRT=OFF |
是否需要 OPENCV_LINK_RUNTIMEDYNAMIC=ON? |
不需要,它是冗余的(除非你用非常老的 OpenCV 版本) |
| 是否必须升级 CMake? | 不必须,但 ≥3.15 更规范 |
✅ 记住:在 OpenCV + MSVC + 静态库场景下,
BUILD_WITH_STATIC_CRT是控制/MTvs/MD的"总闸"。
只要设置 -D BUILD_WITH_STATIC_CRT=OFF,问题立即解决。